codeforces 757e Bash Plays with Functions

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u011528035/article/details/54952669


题意:

给你两个数 n和r 


可以做r次分解

当r大于0 n可以分解成两个因子u和v   u*v=n  

当r 等于0 n分解出的两个因子的gcd要为1


如题意所给的公式来计算最终结果


思路:

仔细观察 在 r相同的情况下 25 和 4  30和42  的答案是相同

是由于 他们的构成结构相同  

即n=(a^x)*(b^y)*(c^z) ...      a b c....为他们的素因数 

而其实也可以得知 f(n,r)=f(a^x,r)*f(b^y,r)*f(c^z,r) ..... 

比如 36 (2^2)*(3^2)  2和3的方案分开独立计算 如果最后2和3都是合理的 那么他们合起来的也是合理的


所以只需考虑只有单因子即可 

根据公式其实是  由于u和v是除于2的 且若u v不同 交换位置算不同次数

于是可以列出dp方程式

i 代表系数 r代表层数

dp[i][r]=dp[1][r-1]+dp[2][r-2]+dp[3][r-3]....

即可以算出答案


#include <iostream>
#include <stdio.h>
#include <math.h>
#include <algorithm>
#include <queue>
#include <map>
using namespace std;
#define LL long long
#define MAX 1001000
#define MOD 1000000007
#define LIM 21

LL dp[LIM][MAX];
int p[MAX];
int v[MAX];
int cnt;

void init()
{
    for(int i=2;i<MAX;i++)
    {
        if(!v[i])
        {
            v[i]++;
            p[cnt++]=i;

        }
        for(int j=0;p[j]*i<MAX&&j<cnt;j++)
        {
            v[p[j]*i]=1;
            if(i%p[j]==0)break;
        }
    }

    dp[1][0]=1;
    for(int i=2;i<LIM;i++)
    {
        dp[i][0]=2;
    }

    for(int i=1;i<MAX;i++)
        for(int j=1;j<LIM;j++)
            dp[j][i]=(dp[j-1][i]+dp[j][i-1])%MOD;

}

int main()
{
    init();
    int t,n,r;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&r,&n);
        LL ans=1;
        int tmp=sqrt(n);
        for(int i=0;i<cnt&&tmp>=p[i];i++)
        {
            if(n%p[i]==0)
            {
                int x=1;
                while(n%p[i]==0)
                {
                    x++;
                    n/=p[i];
                }
                ans=(ans*dp[x][r])%MOD;
            }
        }
        if(n!=1)
            ans=(ans*dp[2][r])%MOD;
        printf("%lld\n",ans);
    }
    return 0;
}



猜你喜欢

转载自blog.csdn.net/u011528035/article/details/54952669
今日推荐