zoukankan      html  css  js  c++  java
  • bzoj 4589: Hard Nim【线性筛+FWT+快速幂】

    T了两次之后我突然意识到转成fwt形式之后,直接快速幂每次乘一下最后再逆回来即可,并不需要没此次都正反转化一次……
    就是根据nim的性质,先手必输是所有堆个数异或和为0,也就变成了一个裸的板子

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int N=500005,mod=1e9+7,inv2=500000004;
    int n,m,q[N],tot,bt,lm;
    long long a[N],c[N],r[N];
    bool v[N];
    void dft(long long a[],int f)
    {
    	for(int i=1;i<lm;i<<=1)
    		for(int j=0;j<lm;j+=(i<<1))
    			for(int k=0;k<i;k++)
    			{
    				long long x=a[j+k],y=a[i+j+k];
    				a[j+k]=(x+y)%mod,a[i+j+k]=(x-y+mod)%mod;
    				if(f==-1)
    					a[i+j+k]=a[i+j+k]*inv2%mod,a[j+k]=a[j+k]*inv2%mod;
    			}
    }
    int main()
    {
    	v[1]=1;
    	for(int i=2;i<=50000;i++)
    	{
    		if(!v[i])
    			q[++tot]=i;
    		for(int j=1;j<=tot&&i*q[j]<=50000;j++)
    		{
    			v[i*q[j]]=1;
    			if(i%q[j]==0)
    				break;
    		}
    	}
    	while(~scanf("%d%d",&n,&m))
    	{
    		memset(a,0,sizeof(a));
    		memset(r,0,sizeof(r));
    		bt=0,lm=0;
    		for(int i=1;i<=tot&&q[i]<=m;i++)
    			a[q[i]]=1;
    		for(;(1<<bt)<=m;bt++);
    		lm=(1<<bt);
    		n--;
    		dft(a,1);
    		for(int i=0;i<lm;i++)
    			r[i]=a[i];
    		while(n)
    		{
    			if(n&1)
    			{
    				for(int i=0;i<lm;i++)
    					r[i]=r[i]*a[i]%mod;
    			}
    			for(int i=0;i<lm;i++)
    				a[i]=a[i]*a[i]%mod;
    			n>>=1;
    		}
    		dft(r,-1);
    		printf("%lld
    ",r[0]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    Anniversary party
    1358. 分割树
    我在 impress.js 中学到的小套路
    我对 impress.js 源码的理解
    CSS transition 过渡 详解
    CSS 2D转换 matrix() 详解
    JS 动画基础
    JS 瀑布流布局
    JS 下拉菜单
    JS Resizable Panel 练习
  • 原文地址:https://www.cnblogs.com/lokiii/p/10044812.html
Copyright © 2011-2022 走看看