BZOJ4589: Hard Nim
FWT模板题。
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define LL long long 4 #define MOD 1000000007 5 #define rep(i,x,y) for(int i=(x);i<=(y);++i) 6 #define drep(i,x,y) for(int i=(x);i>=(y);--i) 7 inline int read(){ 8 char ch=getchar();int x=0,f=1; 9 while(ch<'0'||ch>'9'){ 10 if(ch=='-')f=-1; 11 ch=getchar(); 12 } 13 while('0'<=ch&&ch<='9'){ 14 x=x*10+ch-'0'; 15 ch=getchar(); 16 } 17 return x*f; 18 } 19 inline int Power(int x, int y) { 20 int ret = 1; 21 while(y) { 22 if(y & 1) ret = 1ll * ret * x % MOD; 23 x = 1ll * x * x % MOD; y >>= 1; 24 } 25 return ret; 26 } 27 inline void FWT_xor(int *a, int N, int op) { 28 int inv2 = (MOD + 1) / 2; 29 for(int d = 1; d < N; d <<= 1) { 30 for(int i = 0; i < N; i += (d << 1)) { 31 for(int j = 0; j < d; ++ j) { 32 int X = a[i + j], Y = a[i + j + d]; 33 a[i + j] = (X + Y) % MOD; 34 a[i + j + d] = (X + MOD - Y) % MOD; 35 if(op == -1) { 36 a[i + j] = 1ll * a[i + j] * inv2 % MOD; 37 a[i + j + d] = 1ll * a[i + j + d] * inv2 % MOD; 38 } 39 } 40 } 41 } 42 } 43 int a[200010]; 44 int pri[200010], tot; 45 bool vis[200010]; 46 inline void init() { 47 for(int i = 2; i <= 50000; ++ i) { 48 if(!vis[i]) { 49 pri[++ tot] = i; 50 for(int j = i + i; j <= 50000; j += i) { 51 vis[j] = 1; 52 } 53 } 54 } 55 } 56 int main(){ 57 int n, m; 58 init(); 59 while(scanf("%d%d", &n, &m) != EOF) { 60 int N; 61 for(N = 1; N <= m; N <<= 1); 62 for(int i = 0; i < N; ++ i) a[i] = 0; 63 for(int i = 1; i <= tot; ++ i) { 64 if(pri[i] > m) break; 65 a[pri[i]] = 1; 66 } 67 FWT_xor(a, N, 1); 68 for(int i = 0; i < N; ++ i) { 69 a[i] = Power(a[i], n); 70 } 71 FWT_xor(a, N, -1); 72 printf("%d\n", a[0]); 73 } 74 }