前言

  • 最近考试考得最差的一次吧。
  • 考试的时候太浮躁了,T2题都读错。
  • 其实读错题没什么,主要是T1连对拍都不打,于是一些非常智障的错误导致本应AC的代码变成WA0。
  • 以后考试有时间的话对拍还是尽量题题都打……

T1

  • 这场考试也挺奇怪的,我感觉T1应该是三个题里最难的。
  • 考试的时候刚开始一直觉得直接快速幂就行,但后来发现需要考虑行间关系,便很自然的想到正解。
  • 可以把%n后结果相同的列一起考虑,这样可以进行dp
  • 设f[i][j]表示考虑了%n结果不大于i的所有列,一共放了j个棋子的方案数。
  • 则$f[i][j]=\sum\limits_{k=max(0,j-n)}^j f[i-1][j-k]*{{C_n^k}^{m/n+[m\%n>=i]}}$
  • 显然可以滚动。
  • 然后我就滚动不清空,爆零两行泪了……
  • ${C_n^k}^{m/n+[m\%n>=i]}$这个东西可以预处理的。
  • 所以时间复杂度为$\Theta(N^4)$,空间复杂度$\Theta(N^2)$。
  • 注意有(应该有,我不确定)m<n的情况。
#include<cstdio>
using namespace std;
int const N=10002,M=102,mod=1e9+7;
long long fac[N],inv[N];
long long cp[M];
long long f[2][N];
int cf[M];
long long cq[M][2];
inline long long power(long long x,long long y){
    long long ans=1;
    for(;y;y>>=1,x=x*x%mod)
        if(y&1)ans=ans*x%mod;
    return ans;
}
inline long long C(int x,int y){
    return fac[x]*inv[y]%mod*inv[x-y]%mod;
}
inline int max(int x,int y){
    return x>y?x:y;
}
int main(){
    //freopen("3.in","r",stdin);
    //freopen("6.out","w",stdout);
    int n,c;
    long long m;
    scanf("%d%lld%d",&n,&m,&c);
    int lit=n*n,hh=m%n,pc=(m/n)%(mod-1);
    fac[0]=1;
    for(register int i=1;i<=lit;++i)fac[i]=fac[i-1]*i%mod;
    inv[lit]=power(fac[lit],mod-2);
    for(register int i=lit;i;--i)inv[i-1]=inv[i]*i%mod;
    for(register int i=0;i<=n;++i)cp[i]=C(n,i);
    for(register int i=1;i<=hh;++i)cf[i]=1;
    for(register int i=0;i<=n;++i)
        cq[i][0]=power(cp[i],pc),cq[i][1]=cq[i][0]*cp[i]%mod;
    int u=0,v=1;
    f[0][0]=1;
    if(m<n){
        for(register int i=1;i<=m;++i,u=v,v^=1)
            for(register int j=0;j<=c;++j){
                f[v][j]=0;
                for(register int k=max(0,j-n);k<=j;++k)
                    f[v][j]=(f[v][j]+cq[j-k][1]*f[u][k])%mod;
            }
        printf("%lld",f[u][c]);
        return 0;
    }
    for(register int i=1;i<=n;++i,u=v,v^=1)
        for(register int j=0;j<=c;++j){
            f[v][j]=0;
            for(register int k=max(0,j-n);k<=j;++k)
                f[v][j]=(f[v][j]+cq[j-k][cf[i]]*f[u][k])%mod;
        }
    printf("%lld",f[u][c]);
    return 0;
}
View Code

相关文章:

猜你喜欢
  • 2021-12-04
  • 2021-04-05
  • 2021-12-25
相关资源
相似解决方案