数论 + 贪心 - Basic Gcd Problem - 2020牛客暑期多校训练营(第四场)

数论 + 贪心 - Basic Gcd Problem - 2020牛客暑期多校训练营(第四场)

题意:

给定表达式:

{ f c ( x ) = m a x 1 i x 1 c f c ( g c d ( i , x ) ) x > 1 f c ( x ) = 1 x = 1 \begin{cases}f_c(x)=max_{1≤i≤x-1}c·f_c(gcd(i,x))\qquad x>1\\\\f_c(x)=1 \qquad\qquad\qquad\qquad\qquad\qquad\quad x=1\end{cases}

T n c f c ( n ) 1 0 9 + 7 T组测试数据,每组包括两个正整数n和c,输出f_c(n)。答案对10^9+7取模。

数据范围:

1 T 1 0 6 1 n , c 1 0 6 1≤T≤10^6,1≤n,c≤10^6

示例1
输入

2
3 3
10 5

输出

3
25

分析:

f k c k 容易分析得出,f迭代的次数k越多越好,答案为c^k。

n = P 1 a 1 P 2 a 2 . . . P k a k P 1 < P 2 < . . . < P k 贪心地考虑,分解n=P_1^{a_1}P_2^{a_2}...P_k^{a_k},假设P_1<P_2<...<P_k

使 g c d 要使gcd的迭代次数最多,最优的情况就是每次约去一个最小质因子,这样总次数即所有质因子指数之和。

问题:如何快速分解正整数n,得到其所有质因子的指数之和?

T 1 0 9 n 1 0 6 n O ( n ) 本题T≤10^9,n≤10^6,若对每个n逐个分解质因数,时间复杂度为O(\sqrt{n})也还是会超时,

因此只能实现预处理出来。

M [ i ] i 设M[i]表示正整数i的所有质因子的指数之和。

i M [ i ] = 1 ①、若i是质数,则M[i]=1。

P j i P j × i M [ P j × i ] + = M [ i ] + 1 ②、对任意合数,分解其最小质因子P_j与另一个数i的乘积:P_j×i,则M[P_j×i]+=M[i]+1。

线 M 故我们可以线性筛中递推求出M数组。

代码:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
  
#define ll long long
  
using namespace std;
  
const int N=1e6+10, mod=1e9+7;

int primes[N],cnt,M[N];
bool st[N];

void get_prime(int n)
{
    for(int i=2;i<=n;i++)
    {
        if(!st[i]) 
        {
            primes[cnt++]=i;
            M[i]=1;
        }
        for(int j=0;primes[j]*i<=n;j++)
        {
            st[primes[j]*i]=true;
            M[primes[j]*i]+=M[i]+1;
            if(i%primes[j]==0) break;
        }
    }
}

int quick_pow(int a,int b)
{
    int res=1;
    while(b)
    {
        if(b&1) res=(ll)res*a%mod;
        a=(ll)a*a%mod;
        b>>=1;
    }
    return res;
}

int main()
{
    get_prime(1e6);
    int T;
    int n,c;
    cin>>T;
    while(T--)
    {
        scanf("%d%d",&n,&c);
        int k=M[n];
        printf("%d\n",quick_pow(c,k));
    }
    
    return 0;
}

猜你喜欢

转载自blog.csdn.net/njuptACMcxk/article/details/107478093