BZOJ4818: [Sdoi2017]序列计数

BZOJ4818: [Sdoi2017]序列计数

Description

Alice想要得到一个长度为n的序列,序列中的数都是不超过m的正整数,而且这n个数的和是p的倍数。
Alice还希望,这n个数中,至少有一个数是质数。
Alice想知道,有多少个序列满足她的要求。

Input

一行三个数,n,m,p。
1<=n<=10^9,1<=m<=2×10^7,1<=p<=100

Output

一行一个数,满足Alice的要求的序列数量,答案对20170408取模。

Sample Input

3 5 3

Sample Output

33
题解Here!

据说正解是DP+矩阵快速幂。。。

然而我用了生成函数+快速幂,FFT都没用到。。。

首先这题显然补集转化,就是用全部方案减去不含任何质数的方案。

考虑m比较小,我们能大力把<=m的质数全都筛出来。

发现n很大,要么倍增要么快速幂。。。

发现p相当小,所以我们能在mod p的同余系下做啊。

一看到同余系下求方案数立刻想到卷积和生成函数。。。

假设我们有一个多项式f(x),其中 x的系数为 a个数的序列之和 mod p为 i 的方案数(a为我们引入的变量)。

同时我们有另一个多项式g(x),其中 x的系数为b个数的序列之和 mod p为 i 的方案数(b为我们引入的变量)。

那么,我们如果让f(x)和g(x)做卷积的话,新的多项式 x的系数就是(a+b)个数的序列之和 mod p为 i 的方案数。

这就是生成函数了。

回到这个题,我们先初始化多项式f(x),令 x的系数为 1个数的序列之和 mod p为 i 的方案数。

然后我们求出这个多项式的n次方,就是我们需要的答案了。

发现这道题的p很小,我们连FFT都不用,直接用一个多项式类暴力快速幂就行了。复杂度O(m+p2*log2n),跑的飞快。。。

附代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#define MAXN 110
#define MAXM 2000010
#define MOD 20170408
using namespace std;
int n,m,p,k=0,prime[MAXM];
bool np[MAXM*10];
struct node{
	long long num[MAXN];
	node(){memset(num,0,sizeof(num));}
}one,two;
inline int read(){
	int date=0,w=1;char c=0;
	while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
	while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
	return date*w;
}
void make(){
	np[0]=np[1]=true;
	for(int i=2;i<=m;i++){
		if(!np[i])prime[++k]=i;
		for(int j=1;j<=k&&(long long)prime[j]*i<=m;j++){
			np[prime[j]*i]=true;
			if(i%prime[j]==0)break;
		}
	}
	for(int i=1;i<=m;i++){
		one.num[i%p]++;
		if(np[i])two.num[i%p]++;
	}
}
node operator *(const node &x,const node &y){
	node ret;
	for(int i=0;i<p;i++)
	for(int j=0;j<p;j++)
	ret.num[(i+j)%p]=(ret.num[(i+j)%p]%MOD+x.num[i]%MOD*y.num[j]%MOD)%MOD;
	return ret;
}
node mexp(node base,int k){
	node ans=base;
	k--;
	while(k){
		if(k&1)ans=ans*base;
		base=base*base;
		k>>=1;
	}
	return ans;
}
int main(){
	n=read();m=read();p=read();
	make();
	one=mexp(one,n);
	two=mexp(two,n);
	long long ans=(one.num[0]-two.num[0]+MOD)%MOD;
	printf("%lld\n",ans);
	return 0;
}

 

posted @ 2018-05-27 20:54  符拉迪沃斯托克  阅读(324)  评论(0编辑  收藏  举报
Live2D