BZOJ 3823 定情信物 递推

来源:互联网 发布:rt809f编程器驱动程序 编辑:程序博客网 时间:2024/04/30 18:20

题目大意:定义点为零维元素,线为一维元素,面为二维元素,空间为三维元素,以此类推,求n维立方体中各维元素都有多少

令f[i][j]为i维立方体内j维元素的个数

考虑n维立方体中的i维元素,将n维立方体拓展至n+1维空间时(觉得抽象的可以想象平面扩展成立方体)

原先的i维元素增加了一倍,同时原先的i-1维元素变为了i维元素

故有f[i][j]=f[i-1][j]*2+f[i-1][j-1]

经过一系列的推导(我不会怎么推,我是打表之后斜着找规律的),可以得到f[i][j]=2^(i-j)*C(i,j)

然后就有f[n][i]=f[n][i+1]*2*(i+1)/(n-i) 线性求出逆元 从后往前推即可

Update:尼玛谁这么蛋疼加强了数据- -||| 加强后的数据出现了n>=p的情况(其实这个题本来是n<p的,出题人忘记写在题面上了- -)

对当前的值记录p的次数 乘或除一个数的时候对次数进行加减 异或的时候如果次数不为零则异或0

时间复杂度不对啊- - 不管了能卡过去

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define M 10001000using namespace std;long long inv[M],ans=1;int n,p;struct Long_Long{    long long left;    int pow;    Long_Long(long long _):left(_),pow(0) {}    void operator *= (long long x)    {        while(x%p==0)            x/=p,pow++;        left*=x,left%=p;    }    void operator /= (long long x)    {        while(x%p==0)            x/=p,pow--;        left*=inv[x%p],left%=p;    }};void Linear_Shaker(){    int i;    inv[1]=1;    for(i=2;i<=n&&i<p;i++)        inv[i]=(p-p/i)*inv[p%i]%p;}int main(){    int i;    Long_Long temp=1;    cin>>n>>p;    Linear_Shaker();    for(i=n-1;~i;i--)    {        temp*=static_cast<long long>(i+1<<1);        temp/=static_cast<long long>(n-i);        ans^=temp.pow?0:temp.left;        //cout<<(temp.pow?0:temp.left)<<endl;    }    cout<<ans<<endl;}


0 0
原创粉丝点击