• YbtOJ#912神秘语言【结论,欧拉定理】


    正题

    题目链接:http://www.ybtoj.com.cn/problem/912


    题目大意

    给出\(L,R\),求有多少长度在\([L,R]\)之间的字符串满足依次取出所有偶数位置的放在最前面后,与原字符串相同。字符集是所有小写字母。

    \(1\leq Q\leq 5,1\leq L\leq R\leq 10^{10},R-L\leq 5\times 10^4\)


    解题思路

    这个东西可以理解为给出一些相等关系的边,然后求联通块的数量\(G\),然后方案就是\(26^G\)

    \(G(x)\)表示\(x\)的联通块数量。首先奇偶数不一样很麻烦,发现如果对于奇数\(x\)\(G(x)=G(x-1)+1\)(最后一个自己连自己)。所以我们只需要考虑偶数的。

    \(n\)为偶数时给出的条件其实就是\(S_i=S_{2i\%(n+1)}\),然后此时考虑点\(x\),有\(d=gcd(x,n+1)\),那么有\(x=dk\)。我们让\(x\)\(2x\%(n+1)\)连边,考虑求出\(x\)所在环的环长,也就是求一个最小的\(r\)满足\(x\times2^r\equiv x(mod\ \ n+1)\),就是满足\(2^r\equiv1(mod\ \ \frac{n+1}{gcd(x,n+1)})\),后文记做\(ord(\frac{n+1}{gcd(x,n+1)})\)。然后满足\(gcd(x,n+1)=d\)的都在一些大小为\(r\)的环中相互连接,这样的\(x\)\(\varphi(\frac{n+1}{gcd(x,n+1)})\)个。所以这样的环有\(\frac{\varphi(\frac{n+1}{gcd(x,n+1)})}{ord(\frac{n+1}{gcd(x,n+1)})}\),然后改成枚举\(\frac{n+1}{gcd(x,n+1)}\)就有一个比较舒服的式子

    \[G(n)=\sum_{d|n,d>1}\frac{\varphi(d)}{ord(d)} \]

    上面那个\(\varphi\)很好求,考虑怎么求下面那个\(ord\)
    和原根类似的使用试除法,首先根据欧拉定理肯定有\(ord(n)|\varphi(n)\)。然后考虑对于\(\varphi(n)\)的每个约数\(x\)如果满足\(2^{\frac wx}\equiv 1(mod\ \ n)\)就代表可以除去这个\(x\)

    但是这样每次来搞还是很慢,这里还有一个挺显然的结论

    \[gcd(x,y)=1\Rightarrow ord(x\times y)=lcm(\ ord(x),ord(y)\ ) \]

    证明的话首先定理\(a=lcm(x,y)\),再设一个\(2^b\equiv 1(mod\ xy)\),那么有\(2^{b-a}\equiv1(mod\ xy)\),然后这样更相减损下去最后就有\(2^{gcd(a,b)}\equiv 1(mod\ xy)\),所以如果\(b<a\)那么有,然后因为\(a=lcm(x,y)\)也就是这个就是新的最小的\(gcd\)

    所以我们就只需要求出所有需要的\(ord(p^k)\)就好了。

    然后我们可以先枚举\(\sqrt R\)以内的质数然后来给所有\([L,R]\)中的数质因数分解,然后对于里面的每个\(x\)用搜索来求所有的约数。


    code

    #pragma GCC optimize(2)
    %:pragma GCC optimize(3)
    %:pragma GCC optimize("Ofast")
    %:pragma GCC optimize("inline")
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<map>
    #include<vector>
    #include<cctype>
    #define ll __int128
    using namespace std;
    const ll N=1e5+10,P=1e9+7;
    ll q,L,R,ans,tot,cnt,G;
    ll pri[N],phi[N],mk[N][35],p[35],c[35];
    bool v[N];vector<ll >cp[N];
    map<ll,map<ll,ll> >mp;
    ll read() {
    	ll x=0,f=1; char c=getchar();
    	while(!isdigit(c)) {if(c=='-')f=-f;c=getchar();}
    	while(isdigit(c)) x=(x<<1)+(x<<3)+c-48,c=getchar();
    	return x*f;
    }
    void print(ll x){
    	if (x>9) print(x/10); putchar(x%10+48); return;
    }
    ll power(ll x,ll b,ll P){
    	ll ans=1;
    	while(b){
    		if(b&1)ans=ans*x%P;
    		x=x*x%P;b>>=1;
    	}
    	return ans;
    }
    ll ord(ll p,ll k){
    	if(p<N&&mk[p][k])return mk[p][k];
    	if(p>pri[cnt]&&mp[p][k])return mp[p][k];
    	ll m=power(p,k,1e18),x,w=p-1;x=m/p*(p-1); 
    	while(x%p==0){
    		ll z=power(2,x/p,m);
    		if(z!=1)break;x/=p;
    	}
    	if(w>=L&&w<=R+2){
    		ll wz=w-L;
    		for(ll wc=0;wc<cp[wz].size();wc++){
    			ll i=cp[wz][wc];
    			while(x%pri[i]==0){
    				ll z=power(2,x/pri[i],m);
    				if(z!=1)break;x/=pri[i];
    			}
    			while(w%pri[i]==0)w/=pri[i];
    		} 
    	}
    	else{
    		for(ll i=1;pri[i]*pri[i]<=w&&i<=cnt;i++){
    			if(w%pri[i])continue;
    			while(x%pri[i]==0){
    				ll z=power(2,x/pri[i],m);
    				if(z!=1)break;x/=pri[i];
    			}
    			while(w%pri[i]==0)w/=pri[i];
    		}
    	}
    	if(w>1){
    		if(x%w==0){
    			ll z=power(2,x/w,m);
    			if(z==1)x/=w;
    		}
    	}
    	if(p<N)mk[p][k]=x;
    	else mp[p][k]=x;
    	return x;
    }
    void prime(){
    	phi[1]=1;
    	for(ll i=2;i<N;i++){
    		if(!v[i])pri[++cnt]=i;
    		for(ll j=1;j<=cnt&&i*pri[j]<N;j++){
    			v[i*pri[j]]=1;
    			if(i%pri[j]==0)break;
    		}
    	}
    	return;
    }
    ll lcm(ll x,ll y){
    	ll d=__gcd(x,y);
    	return x*y/d;
    }
    void dfs(ll x,ll ph,ll od){
    	if(x>tot){G+=ph/od;return;}
    	dfs(x+1,ph,od);
    	for(ll i=1,w=p[x];i<=c[x];i++)
    		dfs(x+1,ph*(w/p[x]*(p[x]-1)),lcm(od,ord(p[x],i))),w=w*p[x];
    	return;
    }
    ll work(ll n){
    	tot=0;ll wz=n-L;
    	for(ll w=0;w<cp[wz].size();w++){
    		ll i=cp[wz][w];
    		p[++tot]=pri[i];c[tot]=0;
    		while(n%pri[i]==0)
    			c[tot]++,n/=pri[i];
    	}
    	if(n>1)p[++tot]=n,c[tot]=1;
    	G=-1;dfs(1,1,1);
    	return G;
    }
    signed main()
    {
    //	freopen("language.in","r",stdin);
    //	freopen("language.out","w",stdout);
    //	scanf("%lld",&q);
    	q=read();prime();
    	while(q--){
    //		scanf("%lld%lld",&L,&R);
    		L=read();R=read();ans=0;
    		for(ll i=0;i<=R-L+2;i++)cp[i].clear();
    		for(ll i=1;i<=cnt;i++){
    			ll x=pri[i],l=L/x,r=(R+2)/x;
    			for(ll j=l;j<=r;j++){
    				if(j*x<L||j*x>R+2)continue;
    				cp[j*x-L].push_back(i);
    			}
    		}
    		for(ll i=L/2;i<=R/2;i++){
    			ll tmp=work(i*2ll+1);
    			if(i*2ll>=L)ans=(ans+power(26,tmp,P))%P;
    			if(i*2ll+1<=R)ans=(ans+power(26,tmp+1,P))%P;
    		}
    		print(ans);putchar('\n');
    //		printf("%lld\n",ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    建站始末——(转载)
    阿里云——大神建个人网站分享(转载)
    从零开始建设个人网站
    前端资料——书籍
    【python】*与** 参数问题
    【python】python异常类型
    【python】unittest中常用的assert语句
    【性能测试】性能测试总结<四>
    【性能测试】性能测试总结<三>
    【性能测试】性能测试总结<二>
  • 原文地址:https://www.cnblogs.com/QuantAsk/p/14427201.html
Copyright © 2020-2023  润新知