P4589. Hard Nim题解
题目描述
Claris和NanoApe在玩石子游戏,他们有n堆石子,规则如下:
Claris和NanoApe两个人轮流拿石子,Claris先拿。
每次只能从一堆中取若干个,可将一堆全取走,但不可不取,拿到最后1颗石子的人获胜。 不同的初始局面,决定了最终的获胜者,有些局面下先拿的Claris会赢,其余的局面Claris会负。 Claris很好奇,如果这n堆石子满足每堆石子的初始数量是不超过m的质数,而且他们都会按照最优策略玩游戏,那么NanoApe能获胜的局面有多少种。 由于答案可能很大,你只需要给出答案对10^9+7取模的值。
输入格式
输入文件包含多组数据,以EOF为结尾。 对于每组数据: 共一行两个正整数n和m。 每组数据有1<=n<=10^9, 2<=m<=50000。 不超过80组数据。
输出格式
输入数据 1
3 7
4 13
输出数据 1
6
120
提示
没有写明提示
题目来源
Topcoder SRM 518 Div1 Hard Nim By Tangjz
思路
FWT即可。
代码见下
#include<bits/stdc++.h>
using namespace std;
long long t,m,pp[100005],a[1000006],n=100000;
const long long p=1e9+7;
long long abc(long long a1){
long long c1=0;
while(a1!=0){
c1+=a1%2;
a1/=2;
}
return c1;
}
void xor1(long long *f,long long x){
for(int o=2,k=1;o<=n;o*=2,k*=2){
for(int i=0;i<=n-1;i+=o){
for(int j=0;j<=k-1;j++){
f[i+j]=(f[i+j]+f[i+j+k])%p;
f[i+j+k]=(f[i+j]-f[i+j+k]-f[i+j+k]+p*2)%p;
f[i+j]=(f[i+j]*x)%p;
f[i+j+k]=(f[i+j+k]*x)%p;
}
}
}
return ;
}
long long pow2(long long a1,long long b1){
long long c1=1;
while(b1!=0){
if(b1%2==1){
c1=c1*a1%p;
}
a1=a1*a1%p;
b1/=2;
}
return c1;
}
int main(){
for(int i=2;i<=n;i++){
pp[i]=1;
for(int j=2;j*j<=i;j++){
if(i%j==0){
pp[i]=0;
break;
}
}
}
while(scanf("%lld%lld",&t,&m)!=EOF){
memset(a,0,sizeof(a));
n=1;
while(n<=m){
n*=2;
}
for(int i=0;i<=m;i++){
a[i]=pp[i];
//cout<<a[i]<<endl;
}
xor1(a,1);
for(int i=0;i<=n-1;i++){
a[i]=(pow2(a[i],t))%p;
}
xor1(a,p/2+1);
cout<<a[0]<<endl;
}
return 0;
}

浙公网安备 33010602011771号