zoukankan      html  css  js  c++  java
  • BZOJ5298 CQOI2018交错序列(动态规划+矩阵快速幂)

      显然答案为Σkb·(n-k)a·C(n-k+1,k)。并且可以发现ΣC(n-k,k)=fibn。但这实际上没有任何卵用。

      纯组合看起来不太行得通,换个思路,考虑一个显然的dp,即设f[i][j][0/1]为前i为选了j个1其中第i位是0/1的方案数。这样当然能求出答案,复杂度O(n2)。

      注意到ab很小,并且事实上我们并不需要知道所有的方案数,而是只要求出贡献就可以了。而又有xayb=xa(n-x)b,这个式子显然只要求出所有Σxi就能求了。再由二项式定理,(k+1)b=ΣC(b,i)ki。那么做法就比较显然了,维护上述矩阵大力矩乘即可。

      非常卡常。在bzoj排倒数第二2333

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define ll long long
    #define N 190
    char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
    int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    int n,m,A,B,P,ans,C[N][N];
    inline void inc(int &x,int y){x+=y;if (x>=P) x-=P;}
    int ksm(int a,int k)
    {
        int s=1;
        for (;k;k>>=1,a=1ll*a*a%P) if (k&1) s=1ll*s*a%P;
        return s;
    }
    struct matrix
    {
        int n,a[N][N];
        matrix operator *(const matrix&b) const
        {
            matrix c;c.n=n;memset(c.a,0,sizeof(c.a));
            for (int i=0;i<n;i++)
                for (int j=0;j<b.n;j++)
                    for (int k=0;k<b.n;k++)
                    inc(c.a[i][j],1ll*a[i][k]*b.a[k][j]%P);
            return c;
        }
    }f,a;
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj5298.in","r",stdin);
        freopen("bzoj5298.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        m=n=read(),A=read(),B=read(),P=read();
        C[0][0]=1;
        for (int i=1;i<N;i++)
        {
            C[i][0]=C[i][i]=1;
            for (int j=1;j<i;j++)
            C[i][j]=(C[i-1][j-1]+C[i-1][j])%P;
        }
        f.n=1;f.a[0][0]=1;
        a.n=A+B+1<<1;
        for (int i=0;i<=A+B;i++) a.a[i][i]++,a.a[i+A+B+1][i]++;
        for (int i=0;i<=A+B;i++)
            for (int j=i;j<=A+B;j++)
            inc(a.a[i][j+A+B+1],C[j][i]);
        for (;n;n>>=1,a=a*a) if (n&1) f=f*a;
        for (int i=0;i<=A+B;i++) inc(f.a[0][i],f.a[0][i+A+B+1]);
        for (int i=B;i<=A+B;i++)
        if (i-B&1) inc(ans,P-1ll*f.a[0][i]*ksm(m,A+B-i)%P*C[A][i-B]%P);
        else inc(ans,1ll*f.a[0][i]*ksm(m,A+B-i)%P*C[A][i-B]%P);
        cout<<ans;
        return 0;
    }
  • 相关阅读:
    Windows下载Vim
    分享:分享几个程序员使用的网站
    分享:C语言大礼包(PDF)
    将vscode打造成强大的C/C++ IDE
    最适合做C/C++开发的IDE
    bzoj 2244
    bzoj 1492
    bzoj 3262
    bzoj 1176
    bzoj 2961
  • 原文地址:https://www.cnblogs.com/Gloid/p/10111816.html
Copyright © 2011-2022 走看看