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; 	
}
posted @ 2026-02-06 17:07  bz02_2023f2  阅读(2)  评论(0)    收藏  举报  来源