Codeforces Round #588 (Div. 2) C——Primes and Multiplication(唯一分解定理)

題目鏈接

C.Anadi and Domino

題意
給定 x,nx,n,求i=1nf(x,i)\displaystyle\prod_{i=1}^{n}f(x,i)

定義1: 對於g(x,p)g(x,p),定義kkxx 可以整除 pp 的最大次冪,那麼g(x,p)=pkg(x,p)=p^k
例如
g(45,3)=9g(45,3)=9323^2可以整除4545,但是333^3就不可以整除4545,所以k=2,g(45,3)=32=9k = 2,g(45,3)=3^2=9

定義2:f(x,y)=pg(y,p)[px]\displaystyle f(x,y) =\prod_{p}g(y,p)[p是x的質因子]

思路
現將 xx 用試除法分解質因子,然後根據一個推論:

[1,n] 中因子中含有 i 的數字個數是ni\displaystyle\lfloor\frac{n}{i}\rfloor
kuangbin的練習中(J)也用過這個推論。

找出所有的然後每次累乘 qpow(p[i],n / p[i]),在乘的過程中取餘即可。(qpow是快速冪)

下面以x=12,n=11x=12,n = 11來舉例:

先打出所有的f(x,i),i<=nf(x,i),i <= n,分解 121222 32^2\ 3
在這裏插入圖片描述先將 [1,11][1,11] 中因子有22的數字 中的22先提出來乘,2,4,6,8,102,4,6,8,10一共55個數 ,就乘上252^5
這樣上圖就變成這樣
灰色代表我們已經乘過了
在這裏插入圖片描述
之後將 11 / 211\ / \ 2(整除),得到55,再找[1,5][1,5]中 因子有22的數字,是2,42,4一共22個數,乘上222^2
這一步相當於把第二張圖中,第 44 項和第 88 項的 22 也給乘掉。
這樣所有的 22就都乘完了

之後的質因子就都是這樣乘,這種方法有點埃式篩法的意思。

#include<bits/stdc++.h>
#define ll __int64
using namespace std;

const int N = 1e5 + 7;
const int mod = 1e9 + 7;

int c[N],p[N],tot = 0;
int prime[N],prime_tot = 0;
bool prime_tag[N];
ll x,n;

void get_prime(){
	
	for(ll i = 2; i < N; i++) prime_tag[i] = true;
	for(ll i  = 2; i < N; i++){
		for(ll j = i * i ; j < N; j += i)
			prime_tag[j] = false;
	}
	for(int i = 2; i < N; i++)
		if(prime_tag[i]) prime[prime_tot++] = i; 
}
ll qpow(ll a,ll b){
	ll res = 1;
	while(b){
		if(b & 1){
			res = res * a % mod; 
		}
		a = a * a % mod;
		b >>= 1;
	}
	return res;
}
void divide(ll n) {
    for(int i = 0 ; i < prime_tot && prime[i]*prime[i] <= n; i++) {
        if(n % prime[i] == 0) {
            p[++tot] = prime[i];
            while(n % prime[i] == 0 && n > 1) {
               	c[tot]++;
                n /= prime[i];
            }
            if(n == 1) break;
        }
    }
    if(n > 1) {
        p[++tot] = n;
        c[tot] = 1;
    }
}
ll solve(ll m){
	ll res = 1,t;
	divide(x);
	for(int i = 1 ; i <= tot; i++){
		t = m;
		while(t){
			res = res % mod * qpow(p[i],t / p[i]) % mod;
			t /= p[i];
			//printf("res = %I64d \n",res);
		}
	}
	return res;
}
int main(){
	ll ans;
	get_prime();
	scanf("%I64d%I64d",&x,&n);
	ans = solve(n);
	printf("%I64d",ans);
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章