• [BZOJ4589]Hard Nim


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

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

    Input
    输入文件包含多组数据,以EOF为结尾。
    对于每组数据:
    共一行两个正整数n和m。
    每组数据有1<=n<=10^9, 2<=m<=50000。
    不超过80组数据。

    Output
    每行一个整数,表示答案

    Sample Input
    3 7
    4 13

    Sample Output
    6
    120


    其实这题就是询问从m个质数中选出n个,问异或和为0的方案数

    然后直接上FWT快速幂就好了

    而且由于FWT这玩意没有精度问题,你可以FWT完后全部做一遍快速幂,最后整个IFWT回来就好

    /*program from Wolfycz*/
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define inf 0x7f7f7f7f
    using namespace std;
    typedef long long ll;
    typedef unsigned int ui;
    typedef unsigned long long ull;
    inline int read(){
    	int x=0,f=1;char ch=getchar();
    	for (;ch<'0'||ch>'9';ch=getchar())	if (ch=='-')    f=-1;
    	for (;ch>='0'&&ch<='9';ch=getchar())	x=(x<<1)+(x<<3)+ch-'0';
    	return x*f;
    }
    inline void print(int x){
    	if (x>=10)	print(x/10);
    	putchar(x%10+'0');
    }
    const int N=5e4,M=2e5,p=1e9+7,inv=(p+1)>>1;
    int prime[N+10],A[M+10];
    bool inprime[N+10];
    int mlt(int a,int b){
    	int res=1;
    	for (;b;b>>=1,a=1ll*a*a%p)	if (b&1)	res=1ll*res*a%p;
    	return res;
    }
    void prepare(){
    	int tot=0;
    	for (int i=2;i<=N;i++){
    		if (!inprime[i])	prime[++tot]=i;
    		for (int j=1;j<=tot&&i*prime[j]<=N;j++){
    			inprime[i*prime[j]]=1;
    			if (i%prime[j]==0)	break;
    		}
    	}
    	prime[0]=tot;
    }
    void div(int &x){x=1ll*x*inv%p;}
    void FWT(int *a,int n,int flag){
    	for (int i=2;i<=n;i<<=1){
    		for (int j=0;j<=n;j+=i){
    			for (int k=0;k<i>>1;k++){
    				int x=a[j+k],y=a[j+k+(i>>1)];
    				a[j+k]=(x+y)%p,a[j+k+(i>>1)]=(x-y+p)%p;
    				if (flag==-1)	div(a[j+k]),div(a[j+k+(i>>1)]);
    			}
    		}
    	}
    			
    }
    int main(){
    	prepare();
    	int n,m;
    	while (~scanf("%d%d",&n,&m)){
    		int M;
    		for (M=1;M<=m;M<<=1);
    		for (int i=0;i<M;i++)	A[i]=0;
    		for (int i=1;i<=prime[0]&&prime[i]<=m;i++)	A[prime[i]]=1;
    		FWT(A,M,1);
    		for (int i=0;i<M;i++)	A[i]=mlt(A[i],n);
    		FWT(A,M,-1);
    		printf("%d
    ",A[0]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    06_springboot热部署
    05_springboot多配置文件
    04_springBoot端口和上下文路径
    03_springboot错误处理.md
    02_springboot部署-jar和-war的方式
    01_idea创建springboot
    Vue学习笔记
    Java使用Swing实现五子棋。
    我的开源项目
    Java常用库和工具类
  • 原文地址:https://www.cnblogs.com/Wolfycz/p/10436428.html
Copyright © 2020-2023  润新知