记录编号 443775 评测结果 AAAAAAAAAAAAAAAAAAAA
题目名称 [NOIP 2016]组合数问题 最终得分 100
用户昵称 Gravatarnonamenotitle 是否通过 通过
代码语言 C++ 运行时间 0.835 s
提交时间 2017-09-01 10:17:49 内存使用 46.32 MiB
显示代码纯文本
#include <bits/stdc++.h>
using namespace std;
const int maxn=2000+5;
int dp[maxn][maxn];
int t,k,n,m;
int hav[maxn][maxn],sum[maxn][maxn];
map<int ,int > divk;
int havk(int sol,int x){
    int ret=0;
    while(x%sol==0) x/=sol,ret++;
    return ret;
}
map<int ,int > divisor(int x){
    map<int,int > ret;ret.clear();
    for(int i=2;i*i<=x;i++){
        while(x%i==0) x/=i,ret[i]++;
    }
    if(x!=1) ret[x]++;
    return ret;
}
void proce(){
    for(map<int ,int >::iterator ite=divk.begin();ite!=divk.end();++ite){
        int u=ite->first;
        for(int i=1;i<maxn;i++){
            hav[u][i]=havk(u,i);
        }
        for(int i=1;i<maxn;i++) sum[u][i]=sum[u][i-1]+hav[u][i];
    }
}
int main()
{
    freopen("problem.in","r",stdin);
    freopen("problem.out","w",stdout);
    scanf("%d%d",&t,&k);
    divk=divisor(k);
    /*for(map<int ,int >::iterator ite=divk.begin();ite!=divk.end();ite++){
        printf("%d: %d\n",ite->first,ite->second);
    }puts("");*/
    proce();
    for(int i=1;i<maxn;++i){
        for(int j=1;j<=i;++j){
            bool can=true;
            for(map<int ,int >::iterator ite=divk.begin();ite!=divk.end();++ite){
                int u=ite->first;
                if(sum[u][i]-(sum[u][j]+sum[u][i-j])<ite->second) {can=false;break;}
            }
            dp[i][j]=can?1:0;
        }
    }
    /*for(int i=0;i<10;i++){
        for(int j=0;j<10;j++){
            printf("dp[%d][%d]=%d\n",i,j,dp[i][j]);
        }puts("");
    }*/
    for(int i=1;i<maxn;++i){
        for(int j=1;j<=i;++j) dp[i][j]+=dp[i][j-1];
        for(int j=i+1;j<maxn;++j) dp[i][j]=dp[i][j-1];
    }

    for(int i=1;i<maxn;++i){
        for(int j=0;j<maxn;j++){
            dp[i][j]=dp[i-1][j]+dp[i][j];
        }
    }
    /*for(int i=0;i<10;i++){
        for(int j=0;j<10;j++){
            printf("dp[%d][%d]=%d\n",i,j,dp[i][j]);
        }puts("");
    }*/
    for(int z=0;z<t;++z){
        scanf("%d%d",&n,&m);
        printf("%d\n",dp[n][min(n,m)]);
    }
    return 0;
}