【Numeroteoria】 Sumdiv (Löydä X ^ Y-tekijöiden summa)

Number Theory Sumdiv



Tarkastellaan kahta luonnollista lukua A ja B. Olkoon S kaikkien A ^ B: n luonnollisten jakajien summa. Määritä S modulo 9901 (loppuosa S: n jaosta 9901: llä).
Tulo
Ainoa rivi sisältää kaksi luonnollista lukua A ja B, (0<= A,B <= 50000000)separated by blanks.
Tuotos
Lähdön ainoa rivi sisältää S modulo 9901: n.
Näytesyöttö
2. 3
Näyte tuotos
viisitoista
Vihje
2 ^ 3 = 8.
8: n luonnolliset jakajat ovat: 1,2,4,8. Heidän summa on 15.
15 modulo 9901 on 15 (sen pitäisi olla lähtö).

Otsikko:
Etsi tekijän X ^ Y kertoimien summa ja tulos on modulo 9901.



Ajatteluanalyysi:
on mallikysymys tekijöiden summan löytämiseksi. Siinä käytetään alkulukuseulan, yhdistelmäluvun hajoamisen, kongruenssilauseen, nopean kertolaskun, nopean tehon ja tekijöiden summan kaavaa. Tämän kysymyksen tekemisessä on useita sudenkuoppia:



  1. Sinun on käytettävä nopeaa kertomista nopean tehon optimoimiseksi, muuten se puhkeaa pitkään
  2. Tätä kysymystä ei voida tehdä käänteisillä elementeillä. Vaikka moduuli 9901 on alkuluku, kun a on kerroin 9901: lle, se ei voi olla keskenään alkuluku. Tarve käyttää kongruenssilauseen jakokaavaa.

Aseta AC-koodi suoraan alle.



#include #include #include #define ll long long using namespace std const int N = 200000 ll prime[N] int vis[N] int t ll fast_mul(ll x,ll y,ll mod){ //Fast multiplication (x*y modulo to prevent overflow and speed up) ll res=0 while(y){ if(y&1) res=(res+x)%mod x=(x+x)%mod y /= 2 } return res } ll pow_mod(ll x,ll y,ll mod){ //Fast multiplication optimization fast power ll res=1 while(y){ if(y&1) res=fast_mul(res,x,mod) x=fast_mul(x,x,mod) y /= 2 } return res } void isPrime() //Prime sieve { t=0 memset(vis,0,sizeof(vis)) memset(prime,0,sizeof(prime)) for(ll i=2i<Ni++) { if(!vis[i]) { prime[t++]=i for(ll j=i*ij<Nj+=i) vis[j]=1 } } } //factor[i][0]=pi,factor[i][1]=ai ll factor[100][2] ll cnt //cnt represents the number of prime factors void splitPrime(ll x) //Decompose prime factors { cnt=0 ll t=x for(int i=0prime[i]<=t/prime[i]i++) { factor[cnt][1]=0 while(t%prime[i]==0) //Divisible by prime numbers { factor[cnt][0]=prime[i] while(t%prime[i]==0) //Calculate the number of divisions by a prime number as the power of the prime number { factor[cnt][1]++ t/=prime[i] } cnt++ } } if(t!=1) //t!=1 means t is a prime number { factor[cnt][0]=t factor[cnt][1]=1 cnt++ } } ll sum_factor(ll x, ll y, ll c) //Find the sum of the factors. s(n) = (1+p^1+p^2+...p^e)*s(n') = (p^(e+1)-1) / (p-1) * s( n') { //Let g(p, e) = (p^(e+1)-1) / (p-1), then s(n) = g(p1, e1) * g(p2, e2) * .. . * g(pk, ek) if(x == 0) return 0 splitPrime(x) ll sum = 1 for(int i = 0i < cnti++) { ll b = factor[i][0]-1 ll m = b*c ll a = pow_mod(factor[i][0],y*factor[i][1]+1,m)-1 ll tmp = a/b%c sum *= tmp%c sum = (sum+c)%c } return sum } int main() { isPrime() ll A,B while(~scanf('%lld%lld',&A, &B)) { printf('%lld ',sum_factor(A,B,9901)) } return 0 }

Täydennys: Tietoja tmp-algoritmin selityksestä
kuva