BZOJ4589 Hard Nim 【FWT】

题目链接

BZOJ4589

题解

FWT
模板题

#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
#include<cmath>
#include<map>
#define LL long long int
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define Redge(u) for (int k = h[u]; k; k = ed[k].nxt)
#define cls(s,v) memset(s,v,sizeof(s))
#define mp(a,b) make_pair<int,int>(a,b)
#define cp pair<int,int>
using namespace std;
const int maxn = 100005,P = 1000000007;
int A[maxn],B[maxn],inv2;
int p[maxn],isn[maxn],pi,N = 50000;
inline int qpow(int a,int b){
	int re = 1;
	for (; b; b >>= 1,a = 1ll * a * a % P)
		if (b & 1) re = 1ll * re * a % P;
	return re;
}
void init(){
	inv2 = qpow(2,P - 2);
	for (int i = 2; i <= N; i++){
		if (!isn[i]) p[++pi] = i;
		for (int j = 1; j <= pi && i * p[j] <= N; j++){
			isn[i * p[j]] = true;
			if (i % p[j] == 0) break;
		}
	}
}
void fwt(int* a,int n,int opt){
	for (int i = 1; i < n; i <<= 1)
		for (int j = 0; j < n; j += (i << 1))
			for (int k = 0; k < i; k++){
				int x = a[j + k],y = a[j + k + i];
				a[j + k] = (x + y) % P; a[j + k + i] = (x - y + P) % P;
				if (opt == -1) a[j + k] = 1ll * a[j + k] * inv2 % P,a[j + k + i] = 1ll * a[j + k + i] * inv2 % P;
			}
}
void Power(int* a,int b,int n){
	cls(B,0); B[0] = 1;
	fwt(B,n,1); fwt(a,n,1);
	for (int i = 0; i < n; i++) B[i] = 1ll * B[i] * qpow(a[i],b);
	fwt(B,n,-1);
}
int main(){
	init();
	int n,m;
	while (~scanf("%d%d",&n,&m)){
		cls(A,0);
		for (int i = 1; i <= pi && p[i] <= m; i++)
			A[p[i]] = 1;
		int deg = 1;
		while (deg <= m) deg <<= 1;
		Power(A,n,deg);
		printf("%d\n",B[0]);
	}
	return 0;
}
posted @ 2018-07-02 17:40  Mychael  阅读(131)  评论(0编辑  收藏  举报