1. 程式人生 > >Codechef:Misinterpretation 2/MISINT2

Codechef:Misinterpretation 2/MISINT2

傳送門

題解:
這tm誰出的題,卡了半天常數。

對於特定的 i i ,他的方案數相當於是26的等價類個數次方。觀察到對於奇數等價類只比偶數多1,只用考慮偶數怎麼做。

在偶數意義下, a i =

a 2 i   m o d   n
+ 1
a_i = a_{2i \bmod {n+1}} ,相當於每個點有個出度,顯然等價類是由若干個環拼起來的。

對於一個環內,顯然有 x

2 i x ( m o d n + 1 ) x*2^i \equiv x \pmod {n+1} i i 的最小解就是這個環的大小。

在互質意義下,顯然 i i φ ( n + 1 ) \varphi(n+1) 的因數,我們用試除法即可得到答案,不互質同樣, i i 一定是 φ ( n + 1 ( n + 1 , x ) ) \varphi(\frac{n+1}{(n+1,x)}) 的約數。這樣暴力列舉找迴圈節就可以過了。

掛一個自相矛盾的題解:
在這裡插入圖片描述

#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);
}