HDU 6051 If the starlight never fade(原根+推式子)
阿新 • • 發佈:2019-01-12
() sign cas == lnp ostream tmp clas 同時 。得到\((1+g^{b-a})^i\equiv 1(mod\ p)\)
設\(1+g^{b-a}\equiv g^k(mod\ p)\)(因為原根的性質所以我們一定可以找到這樣的k)。
此時原式為\(g^{k*i} \equiv 1(mod\ p)\)由費馬小定理可以到到\(p-1 \mid k*i\)。
這就要求k為\(\frac{p-1}{gcd(p-1,i)}\)的倍數(即至少包含p-1所特有的因子)。由於\(0<k<p-1\),為什麽k不能取0呢?因為$g^{b-a}不會為0,所以\(1+g^{b-1}> 1\)。
所以可以得到這樣的k的數量是\(\frac{p-1}{\frac{p-1}{gcd(p-1,i)}}-1=gcd(p-1,i)-1\) ,這裏因為k不能取0和p-1,所以要減1。
又因為\(1+g^{b-a} \equiv g^k(mod\ p)\)得\(g^b \equiv(g^k-1)*g^a (mod\ p)\),\(y\equiv x*(g^k-1)(mod\ p)\)。每有一個k,y對應一個x。所以對於一個y有\(gcd(p-1,i)-1\)個x對應。
所以可以得出\(f(i)=m*(gcd(p-1,i)-1)\)。
\(\sum_{i=1}^{p-1}i*f(i)\)
\(=m\sum_{i=1}^{p-1}i*gcd(p-1,i)-m*\frac{(p-1)*p}{2}\)
重點是如何求\(\sum_{i=1}^{p-1}i*gcd(p-1,i)\) 。
\(\sum_{i=1}^{p-1}i*gcd(p-1,i)\)
顯然d是p-1的約數
\(=\sum_{d\mid p-1}d\sum_{i=1}^{p-1}i*[gcd(p-1,i)==d]\)
\(=\sum_{d\mid p-1}d^2\sum_{i=1}^{\frac{p-1}{d}}i*[gcd(\frac{p-1}{d},i)==1]\)
然後有一個神奇的變換。
\(\sum_{i=1}^{t}i*[gcd(t,i)==1]=\frac{t*\varphi(t)+[t==1]}{2}\)
為什麽?
令\(t=\frac{p-1}{d}\)就是\(\sum_{i=1}^{t}i*[gcd(t,i)==1]\)
其實就是求1到t中與t互質的數的和。
由更相減損術得若\(gcd(n,i)=1\)則\(gcd(n,n-i)=1\)
所以一個與\(t\)互質的數\(x\),\(t-x\)也與\(t\)互質。
所以與t互質的數成對出現,設這一對數為a,b,有\(a+b=t\)。
所以\(\sum_{i=1}^{t}i*[gcd(t,i)==1]=\frac{t*\varphi(t)+[t==1]}{2}\)
故原式可以化為
\(\sum_{d\mid p-1}d^2\sum_{i=1}^{\frac{p-1}{d}}i*[gcd(\frac{p-1}{d},i)==1]\)
\(=\sum_{d\mid p-1}d^2*\frac{\frac{p-1}{d}*\varphi(\frac{p-1}{d})+[\frac{p-1}{d}==1]}{2}\)
帶回去求解即可。
復雜度?\(O(能過)\),因為求約數可以先掃出質數來優化,所以\(\sqrt{\frac{p}{lnp}}*\sqrt{p}=\sqrt{\frac{p^2}{lnp}}\)差不多兩億,不是很大。而且求歐拉函數是求p-1的約數的約數,一定比\(\sqrt{p}\)小,所以能過?
題目大意:
設\(f(i)\)為使\((x+y)^i \equiv x^i (mod\ p)\)成立的(x,y)的對數。其中\(1 \leq x \leq p-1 , 1\leq y\leq m\),m,p給定且p是一個質數。求\(\sum_{i=1}^{p-1}i*f(i)\),p<=1e9+7,m<=p-1
思路
我們考慮用原根去代換x,y。
設g為p的一個原根,\(g^a\equiv x(mod \ p),g^b \equiv y(mod \ p)\)。
然後我們用\(g\)去代換\(x,y\)。\((g^a+g^b)^i\equiv g^{a*i}(mod\ p)\)然後我們在式子兩邊同時除一個\(g^{a*i}\)
設\(1+g^{b-a}\equiv g^k(mod\ p)\)(因為原根的性質所以我們一定可以找到這樣的k)。
此時原式為\(g^{k*i} \equiv 1(mod\ p)\)由費馬小定理可以到到\(p-1 \mid k*i\)。
這就要求k為\(\frac{p-1}{gcd(p-1,i)}\)的倍數(即至少包含p-1所特有的因子)。由於\(0<k<p-1\),為什麽k不能取0呢?因為$g^{b-a}不會為0,所以\(1+g^{b-1}> 1\)。
所以可以得到這樣的k的數量是\(\frac{p-1}{\frac{p-1}{gcd(p-1,i)}}-1=gcd(p-1,i)-1\)
又因為\(1+g^{b-a} \equiv g^k(mod\ p)\)得\(g^b \equiv(g^k-1)*g^a (mod\ p)\),\(y\equiv x*(g^k-1)(mod\ p)\)。每有一個k,y對應一個x。所以對於一個y有\(gcd(p-1,i)-1\)個x對應。
所以可以得出\(f(i)=m*(gcd(p-1,i)-1)\)。
\(\sum_{i=1}^{p-1}i*f(i)\)
\(=m\sum_{i=1}^{p-1}i*gcd(p-1,i)-m*\frac{(p-1)*p}{2}\)
重點是如何求\(\sum_{i=1}^{p-1}i*gcd(p-1,i)\)
\(\sum_{i=1}^{p-1}i*gcd(p-1,i)\)
顯然d是p-1的約數
\(=\sum_{d\mid p-1}d\sum_{i=1}^{p-1}i*[gcd(p-1,i)==d]\)
\(=\sum_{d\mid p-1}d^2\sum_{i=1}^{\frac{p-1}{d}}i*[gcd(\frac{p-1}{d},i)==1]\)
然後有一個神奇的變換。
\(\sum_{i=1}^{t}i*[gcd(t,i)==1]=\frac{t*\varphi(t)+[t==1]}{2}\)
為什麽?
令\(t=\frac{p-1}{d}\)就是\(\sum_{i=1}^{t}i*[gcd(t,i)==1]\)
其實就是求1到t中與t互質的數的和。
由更相減損術得若\(gcd(n,i)=1\)則\(gcd(n,n-i)=1\)
所以一個與\(t\)互質的數\(x\),\(t-x\)也與\(t\)互質。
所以與t互質的數成對出現,設這一對數為a,b,有\(a+b=t\)。
所以\(\sum_{i=1}^{t}i*[gcd(t,i)==1]=\frac{t*\varphi(t)+[t==1]}{2}\)
故原式可以化為
\(\sum_{d\mid p-1}d^2\sum_{i=1}^{\frac{p-1}{d}}i*[gcd(\frac{p-1}{d},i)==1]\)
\(=\sum_{d\mid p-1}d^2*\frac{\frac{p-1}{d}*\varphi(\frac{p-1}{d})+[\frac{p-1}{d}==1]}{2}\)
帶回去求解即可。
復雜度?\(O(能過)\),因為求約數可以先掃出質數來優化,所以\(\sqrt{\frac{p}{lnp}}*\sqrt{p}=\sqrt{\frac{p^2}{lnp}}\)差不多兩億,不是很大。而且求歐拉函數是求p-1的約數的約數,一定比\(\sqrt{p}\)小,所以能過?
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
#define int long long
const int N=1001000;
const int mod=1e9+7;
bool book[N];
int prime[N],cnt,inv,T;
int read(){
int sum=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){sum=sum*10+ch-'0';ch=getchar();}
return sum*f;
}
void pre_work(){
for(int i=2;i<=1000000;i++){
if(book[i]==0)prime[++cnt]=i;
for(int j=1;j<=cnt&&prime[j]*i<=1000000;j++){
book[prime[j]*i]=1;
if(i%prime[j]==0)break;
}
}
}
int ksm(int x,int b){
int tmp=1;
while(b){
if(b&1)tmp=tmp*x%mod;
b>>=1;
x=x*x%mod;
}
return tmp;
}
int phi(int x){
int tmp=x;
int ans=x;
for(int i=1;i<=cnt&&prime[i]*prime[i]<=x;i++){
if(tmp%prime[i]==0){
ans=ans/prime[i]*(prime[i]-1);
while(tmp%prime[i]==0)tmp/=prime[i];
}
}
if(tmp>1)ans=ans/tmp*(tmp-1);
return ans;
}
int work(int x){
int tmp=0;
for(int i=1;i*i<=x;i++){
if(x%i==0){
int a=i*i%mod;
int b=x/i;
int c=phi(b);
int d=(b==1);
tmp=(tmp+a*(b*c%mod+d)%mod*inv%mod)%mod;
if(x/i>i){
int hh=x/i;
int a=hh*hh%mod;
int b=x/hh;
int c=phi(b);
int d=(b==1);
tmp=(tmp+a*(b*c%mod+d)%mod*inv%mod)%mod;
}
}
}
return tmp;
}
signed main(){
T=read();
pre_work();
inv=ksm(2,mod-2);
int now=0;
while(T--){
now++;
int m=read(),p=read();
int tmp=((m*work(p-1)%mod-m*(p-1ll)%mod*p%mod*inv%mod)%mod+mod)%mod;
printf("Case #%lld: %lld\n",now,tmp);
}
return 0;
}
HDU 6051 If the starlight never fade(原根+推式子)