2020牛客暑期多校训练营(第四场)Basic Gcd Problem

题目描述

在这里插入图片描述

分析

看到这道题的主体是一个递推式,那么绝不可能只是简单的套公式
那么就要进行优化
再仔细看一看,发现gcd,c*f(n)(n为某数)。
那么gcd,快速幂,素数筛先打好。

ll gcd(ll x,ll y){return y==0?x:gcd(y,x%y);}//gcd
ll ksm(ll x,ll y)//快速幂拼音首字母
{
    ll ret=1;
    while(y)
    {
        if(y&1) ret=ret*x%mod;
        x=x*x%mod;
        y>>=1;
    }
    return ret;
}

于是发现素数筛不仅仅是把素数筛出来
由递推式可知
f(n)是要最大的,所以要把i的最大因数给存进去

    for(i=2;i<=MAXN;i++)
	 if(!dv[i])
	  for(j=1;j*i<=MAXN;j++)
	   dv[j*i]=max(dv[i*j],j);//素数筛魔改版

然后把式子套进去
注意是多组数据,所以要记忆化

    for(scanf("%lld",&T);T--;)
    {
        scanf("%lld%lld",&n,&c);
        if(n<=num) printf("%lld\n",dp[n]*ksm(c,sum[n]));
        else
        {
            for(int i=num+1;i<=n;i++)
			{
				dp[i]=dp[dv[i]];
				sum[i]=sum[dv[i]]+1;
			}
            num=n;
            printf("%lld\n",dp[n]*ksm(c,sum[n]));
        }
    }

然后AC了

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const ll mod=1e9+7;
const int MAXN=1010101;
bool isprime[MAXN];
ll T,n,c,num,dp[MAXN],sum[MAXN],lis[MAXN];
ll dv[MAXN];
ll i,j,k,l,o,p;
ll gcd(ll x,ll y){return y==0?x:gcd(y,x%y);}
ll ksm(ll x,ll y)
{
    ll ret=1;
    while(y)
    {
        if(y&1) ret=ret*x%mod;
        x=x*x%mod;
        y>>=1;
    }
    return ret;
}
int main()
{
    for(i=2;i<=MAXN;i++)
	 if(!dv[i])
	  for(j=1;j*i<=MAXN;j++)
	   dv[j*i]=max(dv[i*j],j);
    dp[1]=1;
	sum[1]=0;
	num=1;
    for(scanf("%lld",&T);T--;)
    {
        scanf("%lld%lld",&n,&c);
        if(n<=num) printf("%lld\n",dp[n]*ksm(c,sum[n]));
        else
        {
            for(int i=num+1;i<=n;i++)
			{
				dp[i]=dp[dv[i]];
				sum[i]=sum[dv[i]]+1;
			}
            num=n;
            printf("%lld\n",dp[n]*ksm(c,sum[n]));
        }
    }
}

猜你喜欢

转载自blog.csdn.net/qq_46070004/article/details/107486532