• BZOJ3157/BZOJ3516 国王奇遇记(矩阵快速幂/数学)


      由二项式定理,(m+1)k=ΣC(k,i)*mi。由此可以构造矩阵转移,将mi*ik全部塞进去即可,系数即为组合数*m。复杂度O(m3logn),因为大常数喜闻乐见的T掉了。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    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;
    }
    #define N 202
    #define P 1000000007
    int n,m,C[N][N];
    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 (register int i=0;i<n;i++)
                for (register int j=0;j<N;j++)
                    for (register int k=0;k<N;k++)
                    c.a[i][j]=(c.a[i][j]+1ll*a[i][k]*b.a[k][j]%P)%P;
            return c;
        }
    }f,a;
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj3157.in","r",stdin);
        freopen("bzoj3157.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        n=read()+1,m=read();
        C[0][0]=1;
        for (int i=1;i<=m;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;
        }
        a.n=m+2;
        for (int i=0;i<=m;i++)
            for (int j=0;j<=i;j++)
            a.a[j][i]=1ll*m*C[i][j]%P;
        a.a[m][m+1]=a.a[m+1][m+1]=1;
        f.n=1;f.a[0][0]=1;
        for (;n;n>>=1,a=a*a) if (n&1) f=f*a;
        cout<<f.a[0][m+1];
        return 0;
    }
    View Code

      考虑更神的完全想不到的推导:(直接搬了)

      

      就可以做到O(m2)了。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    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;
    }
    #define N 2010
    #define P 1000000007
    int n,m,C[N][N],f[N];
    int ksm(int a,int k)
    {
        if (k==0) return 1;
        int tmp=ksm(a,k>>1);
        if (k&1) return 1ll*tmp*tmp%P*a%P;
        else return 1ll*tmp*tmp%P;
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj3157.in","r",stdin);
        freopen("bzoj3157.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        n=read(),m=read();
        C[0][0]=1;
        for (int i=1;i<=m;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;
        }
        if (m==1) {cout<<(1ll*n*(n+1)>>1)%P;return 0;}
        f[0]=1ll*m*(ksm(m,n)-1)%P*ksm(m-1,P-2)%P;
        for (int i=1;i<=m;i++)
        {
            f[i]=1ll*ksm(n,i)*ksm(m,n+1)%P;
            for (int j=0;j<i;j++)
            if (i-j&1) f[i]=(f[i]-1ll*C[i][j]*f[j]%P+P)%P;
            else f[i]=(f[i]+1ll*C[i][j]*f[j]%P)%P;
            f[i]=1ll*f[i]*ksm(m-1,P-2)%P;
        }
        cout<<f[m];
        return 0;
    }

      甚至可以做到O(m)。不觉得能看懂了。

  • 相关阅读:
    对软件测试的理解
    Android 经典欧美小游戏 guess who
    Shell脚本 | 安卓应用权限检查
    自动化测试 | UI Automator 进阶指南
    Shell脚本 | 截取包名
    自动化测试 | UI Automator 入门指南
    杂谈随感 | 与测试无关
    Shell脚本 | 性能测试之内存
    Shell脚本 | 健壮性测试之空指针检查
    "java.lang.IllegalStateException: No instrumentation registered! Must run under a registering instrumentation."问题解决
  • 原文地址:https://www.cnblogs.com/Gloid/p/9668438.html
Copyright © 2020-2023  润新知