• bzoj 4589: Hard Nim


    Time Limit: 10 Sec Memory Limit: 128 MB
    Submit: 2106 Solved: 1126
    [Submit][Status][Discuss]
    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

    这个博弈显然 是NIM游戏不过是想让我们求出有多少局面使得 石子的异或和为0 这样才能保证后手获胜。
    (注意读题 都是质数 我读成第m个质数了。。这导致我对题意理解存在偏差。。

    那么这道题就很显然了 设f[i][j]前i堆棋子异或和为j的方案数。显然可以快速幂优化。显然这类似于卷积的形式 FWT异或优化即可。
    (我是不会告诉你我读错题都能想出来这些东西的。。

    当然这道题 有一个trick我们不需要再快速幂中使用FWT 而是在FWT中使用快速幂。

    考虑FWT吧A这个多项式变成A' 我们想要在异或运算下求出(A^n)

    可以考虑FWT转换完之后 对于 AB=C 这里运算被定义为卷积异或运算。而我们FWT做的是 A->A' B->B' (A'cdot B'=C')这里·的运算为点积。

    可以发现上述(A^n)相当于 n个A做*运算我们把这n个都变成FWT进行点积运算 最后再转换回来即可得到结果。

    所以FWT套快速幂 要比快速幂套FWT快的多。总复杂度mlogm*T(数据组数。

    注意:

    FFT,NTT只适用于被套于快速幂之中。因为NTT的原理和FWT的原理可以说并不相同。

    int n,m,top,maxx=50000;
    int p[MAXN],v[MAXN],lim;
    ll f[MAXN];
    inline void prepare()
    {
    	for(int i=2;i<=maxx;++i)
    	{
    		if(!v[i])v[i]=p[++top]=i;
    		for(int j=1;j<=top;++j)
    		{
    			if(maxx/i<p[j])break;
    			v[i*p[j]]=p[j];
    			if(v[i]==p[j])break;
    		}
    	}
    }
    inline int fast_pow(ll b,ll p)
    {
    	ll cnt=1;
    	while(p)
    	{
    		if(p&1)cnt=cnt*b%mod;
    		b=b*b%mod;
    		p=p>>1;
    	}
    	return cnt;
    }
    inline void FWT_xor(ll *a,int op)
    {
    	for(int len=2;len<=lim;len=len<<1)
    	{
    		int mid=len>>1;
    		for(int j=0;j<lim;j+=len)
    			for(int i=0;i<mid;++i)
    			{
    				f[i+j]=(f[i+j]+f[i+j+mid])%mod;
    				f[i+j+mid]=(f[i+j]-f[i+j+mid]-f[i+j+mid])%mod;
    				f[i+j]=f[i+j]*op%mod;f[i+j+mid]=f[i+j+mid]*op%mod;
    			}
    	}
    }
    int main()
    {
    	freopen("1.in","r",stdin);
    	prepare();
    	while(gt(n)==1)
    	{
    		gt(m);
    		memset(f,0,sizeof(f));
    		for(int i=1;i<=top&&p[i]<=m;++i)++f[p[i]];
    		lim=1;while(lim<=m)lim=lim<<1;
    		FWT_xor(f,1);
    		for(int i=0;i<lim;++i)f[i]=fast_pow(f[i],n);
    		FWT_xor(f,fast_pow(2,mod-2));
    		printf("%lld
    ",(f[0]+mod)%mod);
    	}
    	return 0;
    }
    
  • 相关阅读:
    聊聊Unity2018的LWRP和混合光照
    不能直接获取?聊聊如何在Shader Graph中获取深度图
    还原堆栈信息,分析地形系统使用ASTC格式的纹理导致Crash的问题
    巧妙设置Texture Type,将ShadowMask内存占用变成之前的1/4
    开发自定义ScriptableRenderPipeline,将DrawCall降低180倍
    Signed Distance Field Shadow in Unity
    Daily Pathtracer!安利下不错的Pathtracer学习资料
    聊聊LightProbe原理实现以及对LightProbe数据的修改
    Scala学习笔记(六):本地函数、头等函数、占位符和部分应用函数
    Scala学习笔记(五):内建控制循环
  • 原文地址:https://www.cnblogs.com/chdy/p/12459568.html
Copyright © 2020-2023  润新知