Codechef:Misinterpretation 2/MISINT2
阿新 • • 發佈:2018-11-01
題解:
這tm誰出的題,卡了半天常數。
對於特定的 ,他的方案數相當於是26的等價類個數次方。觀察到對於奇數等價類只比偶數多1,只用考慮偶數怎麼做。
在偶數意義下, ,相當於每個點有個出度,顯然等價類是由若干個環拼起來的。
對於一個環內,顯然有 , 的最小解就是這個環的大小。
在互質意義下,顯然 是 的因數,我們用試除法即可得到答案,不互質同樣, 一定是 的約數。這樣暴力列舉找迴圈節就可以過了。
掛一個自相矛盾的題解:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int LIM=1e5, B=3e6, N=LIM+50;
inline LL mul(LL a,LL b,LL mod) {return (mod<2e9) ? a*b%mod : ((a*b-(LL)((long double)a/mod*b+1e-7)*mod+mod)%mod);}
inline LL power(LL a,LL b,LL mod) {
LL rs=1;
for(;b;b>>=1,a=mul(a,a,mod))
if(b&1) rs=mul(rs,a,mod);
return rs;
}
LL divc[N],inv[N]; int dc;
struct sieve {
int pr[B+50],npr[B+50],pt;
int mnpr[B+50];
LL ord[N];
sieve() {
for(int i=2;i<=B;i++) {
if(!npr[i]) {
pr[++pt]=i;
mnpr[i]=i;
if(i<=LIM) ord[i]=(i==2) ? 0 : getord(i);
}
for(int j=1;j<=pt;j++) {
LL k=i*pr[j]; if(k>B) break;
npr[k]=1; mnpr[k]=pr[j];
if(!(i%pr[j])) break;
}
}
}
LL getord(LL v) {
LL j=v-1; dc=0;
for(int i=1;i<=pt && (LL)pr[i]*pr[i]<=j && pr[i]<=LIM;++i) {
while(!(j%pr[i])) {
if(divc[dc]!=pr[i]) divc[++dc]=pr[i];
j/=pr[i];
}
if(j<=B) {
while(j!=1) {
int t=mnpr[j];
divc[++dc]=t;
while(!(j%t)) j/=t;
}
}
}
j=v-1;
for(int i=1;i<=dc;i++)
while((!(j%divc[i])) && power(2,j/divc[i],v)==1) j/=divc[i];
return j;
}
} s;
typedef pair <LL,int> pii;
pii fac[N][33]; int cc[N];
LL L,R,res[N],val[N],G[N]; double sum;
const int mod=1e9+7;
inline LL lcm(LL a,LL b) {return a/__gcd(a,b)*b;}
inline void dfs(int o,int p,LL ph,LL len) {
if(p==cc[o]) return;
for(int i=p;i<cc[o];i++) {
pii &v=fac[o][i];
LL p2=ph*(v.first-1), l2=(v.first>LIM) ? res[o] : s.ord[v.first];
for(int j=1;j<=v.second;j++) {
LL vi=lcm(len,l2);
sum+=(double)p2/vi;
dfs(o,i+1,p2,vi);
p2=p2*v.first;
if(j^v.second) l2*=v.first;
}
}
}
unordered_map <LL,LL> ss;
unordered_map <LL,LL> :: iterator iter;
inline int calcG(int p,LL L) {
if(L==1 && !p) return G[p]=0;
iter=ss.find(p+L);
if(iter==ss.end()) sum=0, dfs(p,0,1,1), ss[p+L]=(LL)(sum+0.1);
else sum=iter->second;
G[p]=(LL)(sum+0.1);
return power(26,G[p],mod);
}
inline void solve(int o) {
int ans=0; cin>>L>>R;
++L; ++R;
int tag=0; if(!(L&1)) tag=1, --L;
for(int i=0;i<=R-L;i++) val[i]=i+L, cc[i]=0;
for(int i=1;i<=s.pt && s.pr[i]<=R && s.pr[i]<=LIM;++i) {
for(LL j=((L-1)/s.pr[i]+1)*s.pr[i];j<=R;j+=s.pr[i]) if(j&1)
while(!(val[j-L]%s.pr[i])) {
if(cc[j-L] && s.pr[i]==fac[j-L][cc[j-L]-1].first) ++fac[j-L][cc[j-L]-1].second;
else fac[j-L][cc[j-L]++]=pii(s.pr[i],1);
val[j-L]/=s.pr[i];
}
}
for(int i=0;i<=R-L;i++)
if((!(i&1)) && val[i]>1)
fac[i][cc[i]++]=pii(val[i],1), res[i]=s.getord(val[i]);
for(int i=0;i<=R-L;i++) {
if(i&1) ans=(ans+power(26,G[i-1]+1,mod))%mod;
else ans=(ans+calcG(i,L))%mod;
}
if(tag) ans=(ans-calcG(0,L)+mod)%mod;
cout<<ans<<'\n';
}
int main() {
int T; cin>>T;
while(T--) solve(T);
}