BZOJ3823 定情信物

来源:互联网 发布:vm14安装ubuntu 教程 编辑:程序博客网 时间:2024/04/30 04:37

想象一下一个n维超立方体折跃到n+1维的过程(我是不是星际玩多了-_-)

先把这个n维超立方体复制一份,然后在没对对应点之间连线

那么如果f[i][j]表示i维超立方体中j维元素的数量的话,由上面的过程容易看出f[i][j]=f[i-1][j]*2+f[i-1][j-1]

由归纳法不难证明形如若有f[i][j]=f[i-1][j]*c+f[i-1][j-1]的递推式,且f[0][0]=1的话,那么f[i][j]=c^(i-j)*C(i,j)

也就是(x+c)^i展开后x的j次方项的系数

那么我们就能O(n)推出n维超立方体中每一维元素的个数了

注意有n>p的情况,记录一下组合数中p出现了多少次即可

这么个破题写了半个晚上,我也真是傻了个逼

#include<iostream>#include<cstring>#include<ctime>#include<cmath>#include<algorithm>#include<iomanip>#include<cstdlib>#include<cstdio>#include<map>#include<bitset>#include<set>#include<stack>#include<vector>#include<queue>using namespace std;#define MAXN 10000010#define MAXM 1010#define ll long long#define eps 1e-8#define MOD 1000000007#define INF 1000000000int n,p;int ine[MAXN];int f[MAXN],c[MAXN];ll ans;int cp;int main(){int i;scanf("%d%d",&n,&p);ine[0]=ine[1]=1;for(i=2;i<=n;i++){ine[i]=(ll)(p-p/i)*ine[p%i]%p;}for(i=1;i<=n;i++){if(!(i%p)){c[i]=c[i/p]+1;f[i]=f[i/p];}else{f[i]=i;}}ll now=1;ll ni2=p+1>>1;for(i=1;i<=n;i++){(now*=2)%=p;}ans=now;for(i=1;i<=n;i++){(now*=ni2)%=p;(now*=ine[f[i]%p])%=p;cp-=c[i];(now*=f[n-i+1])%=p;cp+=c[n-i+1];if(!cp){ans^=now;}}printf("%lld\n",ans);return 0;}/**/


0 0
原创粉丝点击