首页 > 其他分享 >你是不是瞧不起力扣

你是不是瞧不起力扣

时间:2023-10-25 09:11:31浏览次数:34  
标签:int omega sum 是不是 mid 力扣 prod 瞧不起 ll

leetcode 「10·24」程序员节编程竞赛 计算子集

给你三个整数 \(n, k, m\) 。定义 \(S=\{i\mid 1\le i\le nm+k,i\in \mathbb Z\}\)

请返回一个下标从 \(0\) 开始、长度为 \(m\) 的数组 answer,其中 answer[i] 表示符合下列条件集合 \(T\) 的个数。

集合 \(T\) 是集合 \(S\) 的子集。
集合 \(T\) 中所有元素的和对 \(m\) 取余的值恰好为 \(i\) 。
由于答案可能很大,你只需要求出它模 998244353 的结果。

0 <= n <= 10^13
0 <= k < min(m, 500)
1 <= m <= 10^5
n * m + k > 0

\(k\) 是没有用的求出 \(nm\) 的答案再把多出来的那 \(k\) 个物品每个暴力 \(\mathcal{O}(m)\) 合并进去就行。那么现在就是求:

\[\left(\prod_{i=0}^{m-1}(1+x^i)\right)^n\pmod {x^m-1} \]

循环卷积要做 dft,这里思路 和 UOJ 310 黎明前的巧克力 相同,UOJ 310 是直接把 fwt 写下来,这里来试着写一些 DFT,\(f_k\) 即为代入 \(\omega_m^k\) 的值,这里令 \(d=\gcd(k,m)\):

\[\begin{aligned} f_k&=\left(\prod_{i=0}^{m-1}(1+\omega_m^{ik})\right)^n\\ &=\left(\prod_{i=0}^{m/d-1}(1+\omega_{m/d}^{i})\right)^{dn} \end{aligned} \]

这一步是因为 \(i\) 模 \(m/d\) 相同的 \(\omega_m^{ik}\) 值是一样的(单位根的定义),这样化简之后发现指数仅和 \(i\) 有关了,括号里面的形式非常好看,考虑比较经典的等式 \(\prod\limits_{i=0}^{m-1}(x-\omega_m^i)=x^m-1\)(左右两侧均为 \(m\) 次多项式且 \([x^m]\) 均为 \(1\) 故两式相等),将其代入 \(x=-1\) 就有:

\[\begin{aligned} &\prod_{i=0}^{m/d-1}(1+\omega_{m/d}^{i})\\ =&(-1)^{m/d}\prod_{i=0}^{m/d-1}(-1-\omega_{m/d}^i)\\ =&(-1)^{m/d}((-1)^{m/d}-1)\\ =&[m/d\bmod 2=1]2 \end{aligned} \]

于是 \(f_k=[m/d\bmod 2=1]2^{dn}\),这里发现 \(f_k\) 的值仅和 \(d\) 有关,那么在 idft 的时候就可以利用这个转成枚举 \(d\):

\[\begin{aligned} g_k=&\frac{1}{m}\sum_{i=0}^{m-1}f_k\omega_m^{-ik}\\ =&\frac{1}{m}\sum_{d\mid m}f_d\sum_{i=0}^{m/d-1}[\gcd(i,m/d)=1]\omega_{m/d}^{-ik}\\ =&\frac{1}{m}\sum_{d\mid m}f_d\sum_{i=0}^{m/d-1}\sum_{e\mid i,e\mid m/d}\mu(e)\omega_{m/d}^{-ik}\\ =&\frac{1}{m}\sum_{de\mid m}f_d\mu(e)\sum_{0\leq i<m/de}\omega_{m/de}^{-ik}\\ =&\frac{1}{m}\sum_{de\mid m}f_d\mu(e)\frac{m}{de}[\frac{m}{de}\mid k]\\ \end{aligned} \]

我朴素实现了个 \(\mathcal{O}(m(\log m+d(m)))\)。

代码
class Solution {
public:
	typedef long long ll;
	typedef vector<int>vi;
	#define pb emplace_back
	static const int mod=998244353;
    static const int N=100010;
	inline void cadd(int &x,int y){x=(x+y>=mod)?(x+y-mod):(x+y);}
	inline void cdel(int &x,int y){x=(x-y<0)?(x-y+mod):(x-y);}
	inline int add(int x,int y){return (x+y>=mod)?(x+y-mod):(x+y);}
	inline int del(int x,int y){return (x-y<0)?(x-y+mod):(x-y);}
	int qpow(int x,ll y){
		int s=1;
		while(y){
			if(y&1)s=1ll*s*x%mod;
			x=1ll*x*x%mod;
			y>>=1;
		}
		return s;
	}
	ll n,m,k;
	int vis[N];
	vi pr;
	int f[N],g[N];
	vi vec[N];
	void init(){
		for(int i=2;i<=m;i++){
			if(!vis[i])
				pr.pb(i);
			for(auto j:pr){
				if(i*j>m)break;
				vis[i*j]=1;
				if(i%j==0)break;
			}
		}
	}
    ll gcd(ll x,ll y){return !y?x:gcd(y,x%y);}
    vector<int> subsetCounting(long long q, int w, int e) {
    	n=q;k=w;m=e;
		if(n){
			init();
			for(int i=1;i<=m;i++){
				int d=__gcd(1ll*i,m);
				if(m/d%2==1){
					f[i]=qpow(2,1ll*d*n);
				}
			}
			for(auto i:pr){
				for(int j=m/i;j;j--)
					cdel(f[i*j],f[j]);
			}
			for(int i=1;i<=m;i++)if(m%i==0)vec[m].pb(i);
			int iv=qpow(m,mod-2);
			for(int i=1;i<=m;i++){
				for(auto de:vec[m]){
					if(i%(m/de)==0){
						cadd(g[i],1ll*f[de]*(m/de)%mod);
					}
				}
				g[i]=1ll*g[i]*iv%mod;
			}
			g[0]=g[m];
			g[m]=0;
		}
		else g[0]=1;
		for(int i=0;i<=m;i++)f[i]=0;
		for(int i=1;i<=k;i++){
			for(int j=0;j<m;j++)
				cadd(f[(j+i)%m],g[j]);
			for(int j=0;j<m;j++)
				g[j]=add(f[j],g[j]),f[j]=0;
		}
		vi vec;
		for(int i=0;i<m;i++)vec.pb(g[i]);
		return vec;
    }
};

标签:int,omega,sum,是不是,mid,力扣,prod,瞧不起,ll
From: https://www.cnblogs.com/do-while-true/p/17786302.html

相关文章

  • 力扣每日一题+python知识点回顾(六)
    力扣题目:老人的数目(题号:2678)给你一个下标从0开始的字符串details。details中每个元素都是一位乘客的信息,信息用长度为15的字符串表示,表示方式如下:前十个字符是乘客的手机号码。接下来的一个字符是乘客的性别。接下来两个字符是乘客的年龄。最后两个字符是乘客的座位......
  • 力扣每日一题+python知识点回顾(五)
    力扣题目:做菜顺序(题号:1402)一个厨师收集了他n道菜的满意程度satisfaction,这个厨师做出每道菜的时间都是1单位时间。一道菜的「like-time系数」定义为烹饪这道菜结束的时间(包含之前每道菜所花费的时间)乘以这道菜的满意程度,也就是time[i]*satisfaction[i]。返回厨师在准备了一......
  • 力扣每日一题+python知识点回顾(四)
    力扣题目:统计无向图中无法互相到达点对数(题号:2316)给你一个整数n,表示一张无向图中有n个节点,编号为0到n-1。同时给你一个二维整数数组edges,其中edges[i]=[ai,bi]表示节点ai和bi之间有一条无向边。请你返回无法互相到达的不同点对数目。示例一:输入:n=3,edges=[[0,1],[0,2......
  • 力扣每日一题+python知识点回顾(三)
    力扣题目:根据规则将箱子分类(题号:2525)给你四个整数length,width,height和mass,分别表示一个箱子的三个维度和质量,请你返回一个表示箱子类别的字符串。如果满足以下条件,那么箱子是"Bulky"的:箱子至少有一个维度大于等于10^4。或者箱子的体积大于等于10^9。如果箱子的......
  • 力扣每日一题+python知识点回顾(二)
    力扣题目:同积元组(题号:1726)给你一个由不同正整数组成的数组nums,请你返回满足a*b=c*d的元组(a,b,c,d)的数量。其中a、b、c和d都是nums中的元素,且a!=b!=c!=d。示例1:输入:nums=[2,3,4,6]输出:8解释:存在8个满足题意的元组:(2,6,3,4),(2,6,4,3),(6,2,3,4),......
  • 力扣12.整数转罗马数字
    罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。字符数值I1V5X10L50C100D500M1000例如,罗马数字2写做 II ,即为两个并列的1。12写做 XII ,即为 X + I......
  • 力扣每日一题+python知识点回顾
    力扣题目:执行K次操作后的最大分数(题号:2530)给你一个下标从0开始的整数数组nums和一个整数k。你的起始分数为0。在一步操作中:选出一个满足0<=i<nums.length的下标i,将你的分数增加nums[i],并且将nums[i]替换为ceil(nums[i]/3)。返回在恰好执......
  • 力扣乱刷
    一些力扣乱刷,旨在复健。42.接雨水:单调栈。32.最长有效括号:数据结构oj原题,标记所有无效括号的位置即可,用栈维护。84.柱状图中最大的矩形:单调栈。85.最大矩形:对每一行跑一个单调栈。224.基本计算器:中缀转后缀模板题。402.移掉k位数字:每次移除序列中最靠左的极大值点,重复......
  • 力扣-120. 三角形最小路径和
    题目描述给定一个三角形triangle,找出自顶向下的最小路径和。每一步只能移动到下一行中相邻的结点上。相邻的结点在这里指的是下标与上一层结点下标相同或者等于上一层结点下标+1的两个结点。也就是说,如果正位于当前行的下标i,那么下一步可以移动到下一行的下标i或i+1。示例1:......
  • 力扣---137. 只出现一次的数字 II
    给你一个整数数组 nums ,除某个元素仅出现 一次 外,其余每个元素都恰出现 三次。请你找出并返回那个只出现了一次的元素。你必须设计并实现线性时间复杂度的算法且使用常数级空间来解决此问题。 示例1:输入:nums=[2,2,3,2]输出:3示例2:输入:nums=[0,1,0,1,0,1,99]......