bzoj4589 Hard Nim FWT+快速幂

版权声明:虽然是个蒟蒻但是转载还是要说一声的哟 https://blog.csdn.net/jpwang8/article/details/87908129

Description


Claris和NanoApe在玩石子游戏,他们有n堆石子,规则如下:

  1. Claris和NanoApe两个人轮流拿石子,Claris先拿。
  2. 每次只能从一堆中取若干个,可将一堆全取走,但不可不取,拿到最后1颗石子的人获胜。
    不同的初始局面,决定了最终的获胜者,有些局面下先拿的Claris会赢,其余的局面Claris会负。
    Claris很好奇,如果这n堆石子满足每堆石子的初始数量是不超过m的质数,而且他们都会按照最优策略玩游戏,那么NanoApe能获胜的局面有多少种。
    由于答案可能很大,你只需要给出答案对10^9+7取模的值。

1<=n<=10^9, 2<=m<=50000。
不超过80组数据。

Solution


水题。。设f[i,j]表示第i轮异或出j的方案数,FWT转移套一个快速幂就可以了

Code


#include <stdio.h>
#include <string.h>
#include <algorithm>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
#define fill(x,t) memset(x,t,sizeof(x))
#define copy(x,t) memcpy(x,t,sizeof(x))

const int MOD=1000000007;
const int ny2=MOD+1>>1;
const int N=131078;

int a[N],b[N],p[N];

bool np[N];

void FWT(int *a,int n,int f) {
	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 u=a[j+k],v=a[j+k+i];
				a[j+k]=(u+v)%MOD,a[j+k+i]=(u-v+MOD)%MOD;
				if (f==-1) {
					a[j+k]=1LL*a[j+k]*ny2%MOD;
					a[j+k+i]=1LL*a[j+k+i]*ny2%MOD;
				}
			}
		}
	}
}

void pre(int n) {
	for (int i=2;i<=n;++i) {
		if (!np[i]) p[++p[0]]=i;
		for (int j=1;i*p[j]<=n&&j<=p[0];++j) {
			np[i*p[j]]=1;
			if (i%p[j]==0) break;
		}
	}
}

int main(void) {
	pre(N-5);
	for (int n,m;~scanf("%d%d",&n,&m);) {
		fill(a,0);
		for (int i=1;i<=p[0]&&p[i]<=m;++i) {
			a[p[i]]=1;
		}
		int len=1;
		for (;len<=m;len<<=1);
		m=len;
		FWT(a,m,1);
		copy(b,a);
		for (n--;n;n>>=1) {
			if (n&1) for (int i=0;i<m;++i) b[i]=1LL*b[i]*a[i]%MOD;
			for (int i=0;i<m;++i) a[i]=1LL*a[i]*a[i]%MOD;
		}
		FWT(b,m,-1);
		printf("%d\n", b[0]);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/jpwang8/article/details/87908129