一行,四個整數,N、M、x、|S|,其中|S|為集合S中元素個數。第二行,|S|個整數,表示集合S中的所有元素。
一行,一個整數,表示你求出的種類數mod 1004535809的值。
【樣例說明】
Round 1 感謝yts1999上傳
NTT第一題
首先可以發現1004535809=479*2^21+1,而且是一個質數,所以可以用NTT解決。
用f[i][j]表示i個數模m等於g^j的方案數(i為2的整數次冪,g為m的原根),則f[i][j]=∑f[i/2][k]*f[i/2][j-k]。這樣就成了卷積形式,NTT搞定。但n並不一定是2的整數次冪,這裡就要用到快速冪的思想(詳見代碼)。
#include#include #include #include #include #include #define F(i,j,n) for(int i=j;i<=n;i++) #define D(i,j,n) for(int i=j;i>=n;i--) #define ll long long #define maxn 40000 #define mod 1004535809 using namespace std; int n,m,num,s,mg,g,bit,inv; int a[maxn],c[maxn],A[maxn],B[maxn],ind[maxn],rev[maxn]; inline int read() { int x=0,f=1;char ch=getchar(); while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } inline ll power(ll x,int y,int p) { ll ret=1; for(;y;y>>=1,x=x*x%p) if (y&1) ret=ret*x%p; return ret; } inline bool get_order(int x,int m) { int lim=sqrt(m),phi=m-1; F(i,1,lim) if (phi%i==0) { if (power(x,i,m)==1){if (i!=m-1) return false;} if (power(x,phi/i,m)==1){if (phi/i!=m-1) return false;} } return true; } inline int get_primitive_root(int x) { F(i,2,x) if (get_order(i,x)) return i; } inline void ntt(int *a,int flag) { F(i,0,(1< i) swap(a[i],a[rev[i]]); F(i,1,bit) { int y=(1ll*flag*(mod-1)/(1<>1]>>1|((i&1)<<(bit-1)); A[0]=1; F(i,1,s) if (a[i]) B[ind[a[i]]]=1; for(;n;convol(B,B),n>>=1) if (n&1) convol(A,B); printf("%d\n",A[ind[num]]); return 0; }