• 【纪中模拟2019.08.17】【JZOJ3504】运算符


    题目链接

    题意:

      定义运算符$!$如下:

      $$n!k=left{ egin{array} {cc} n!(k-1) imes(n-1)!k, & (n>0,;k>0) \ 1, & (n=0) \ n, & (k=0) \ end{array} ight. $$

      给定$n,\,k$,求$n!k$的不同约数个数,对$1e9+9$取模。

      $0<;nle;1000,;0<;kle;100$

    分析:

      虽然$n!k$的值增长非常迅速,并且不能对它取模,很难分解求答案,但其实不用考虑那么多。

      把$n$和$k$的不同取值得到的$n!k$看成$0sim n imes 0sim k$的矩阵,那么容易发现所有的数值都以第$0$列为因子。

      那么只需要做出$1e3$以内的质数,递推累加指数就可以了。经测得到这样的质数有$168$个。

      设$f_{i,j,p}$表示$n!k$的第$p$个质数的指数。可以把第一维用滚动数组将内存优化到$2$倍。

    实现(100分):

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #define IL inline
    using namespace std;
    typedef long long LL;
    const int N=1000;
    const int K=100;
    const int M=168;
    const int mod=1e9+9;
    
    IL LL add(LL x,LL y){
        return (x+y)%mod;
        
    }
    
    IL LL mul(LL x,LL y){
        return x*y%mod;
        
    }
    
        int n,k;
        
        bool npm[N+3];
        LL prm[M+3];
        int m;
    IL void flt(){
        memset(npm,0,sizeof npm);
        m=0;
        
        for(int i=2;i<=N;i++)
        if(!npm[i]){
            prm[++m]=i;
            for(int j=1;j<=m&&i*prm[j]<=N;j++)
                npm[i*prm[j]]=true;
            
        }
        else 
            for(int j=1;j<=m&&i*prm[j]<=N;j++){
                npm[i*prm[j]]=true;
                if(i%prm[j]==0)
                    break;
                
            }
        
    }
    
        LL f[2][K+3][M+3];
    
    IL void dsv(LL i){
        LL ii=i;
        memset(f[i&1][0],0,sizeof f[i&1][0]);
        for(int j=1;j<=m&&prm[j]<=i;j++)
        while(i%prm[j]==0){
            i/=prm[j];
            f[ii&1][0][j]+=1;
            
        }
        
    }
    
    int main(){
        scanf("%d%d",&n,&k);
        
        flt();
        
        memset(f,0,sizeof f);
        for(LL i=1;i<=n;i++){
            dsv(i);
            for(int j=1;j<=k;j++)
                for(int p=1;p<=m;p++)
                    f[i&1][j][p]=add(f[(i-1)&1][j][p],f[i&1][j-1][p]);
            
        }
        
        LL ans=1;
        for(int i=1;i<=m;i++)
            ans=mul(ans,f[n&1][k][i]+1);
        
        printf("%lld",ans);
    
        return 0;
    
    }
    View Code

    小结:

      观察答案的来源,溯流而上求解。

  • 相关阅读:
    03点云文件常用格式转换(pcd,txt,ply,obj,stl)
    04点云数据结构格式
    vs2015 +ZXing/Zbar的环境配置
    01PCL 点云+vs2015在win10下的环境配置
    07点云的滤波与分割
    gitlabCI/CD部署一个java项目
    k8s 为什么需要数据卷
    gitlab Runner 安装与部署
    gitlab ci/cd介绍
    k8s emptyDir临时数据卷
  • 原文地址:https://www.cnblogs.com/Hansue/p/11370238.html
Copyright © 2020-2023  润新知