zoukankan      html  css  js  c++  java
  • BZOJ 5330 Luogu P4607 [SDOI2018]反回文串 (莫比乌斯反演、Pollard Rho算法)

    题目链接

    (BZOJ) https://www.lydsy.com/JudgeOnline/problem.php?id=5330
    (Luogu) https://www.luogu.org/problem/P4607

    题解

    首先观察一些性质。
    一个回文串可以轮换产生多少个本质不同的串?周期那么多个。
    可是有一种特殊情况,就是对于长度为偶数的回文串(a=ss^Rss^Rss^R...ss^R) ((s^R)表示(s)的reverse), 如果轮换位数恰好等于周期的一半,那么会产生(a'=s^Rss^Rss^Rs...s^Rs), 这是另一个回文串,因此会算重!
    于是我们大胆猜测,设(a)的周期为(T), 则当(T)为偶数时对答案的贡献为(frac{T}{2}), 否则为(T).
    一个简单的证明是,串(a)轮换(d)位和轮换(T-d)位所得到的串互为reverse,若得到了回文串,那么(d=T-d).

    那么现在我们的问题简化了: 设长度为(n)字符集为(m)周期为(T)的回文串有(g(T))个,要求的就是(sum_{d|n}g(d)h(d)), 其中(h(d))为贡献。
    现在考虑怎么算周期为(T)的回文串: 设(G(T))表示有多少个回文串满足(T)是它的周期(但不是最小周期,即周期是(T)的因数),则(G(T)=m^{lceil frac{T}{2} ceil}).
    且有(G(T)=sum_{d|T}g(d)), 由莫比乌斯反演可得(g(T)=sum_{d|T}mu(frac{T}{d})G(d)).
    然后直接枚举因数裸求就可以得到54至60分(当然也可以(g(T)=G(T)-sum_{d|T}g(d)), 但是这样由于复杂度较劣只有30至36分,期望得分是官方题解里给的)

    (nle 10^{18})时,(n)的约数个数(d(n)le 103680).
    推式子: (sum_{d|n}sum_{d'|d}G(d')mu(frac{d}{d'})h(d)=sum_{d|n}sum_{d'|frac{n}{d}}G(d)mu(d')h(dd'))
    观察式子,当(d)为奇数(frac{n}{d})为偶数时,每一个奇数都会和一个偶数配成一对,并且(mu)值相反。因此这种情况对答案贡献为(0).
    在其他情况下,一定满足(h(dd')=h(d)d'), 即(sum_{d|n}G(d)h(d)sum_{d'|frac{n}{d}}d'mu(d'))
    考虑(sum_{d|n}dmu(d))的组合意义,易得原式等于(sum_{d|n}G(d)h(d)prod_{p|frac{n}{d}}(1-p)), 其中(p)为质数
    DFS所有的质因数即可。

    时间复杂度(O(n^{frac{1}{4}}log n+d(n)log n)), 其中(d(n))(n)的约数个数.

    代码

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<ctime>
    #include<algorithm>
    #include<vector>
    #define llong long long
    #define pll pair<llong,llong> 
    #define mkpr make_pair
    using namespace std;
    
    const int N = 103680;
    vector<pll> pfac;
    llong P;
    
    llong quickmul(llong x,llong y,llong mod=P)
    {
    	return (x%mod)*(y%mod)%mod;
    }
    llong quickpow(llong x,llong y,llong mod=P)
    {
    	llong cur = x,ret = 1ll;
    	for(int i=0; y; i++)
    	{
    		if(y&(1ll<<i)) {ret = quickmul(ret,cur,mod)%mod; y-=(1ll<<i);}
    		cur = quickmul(cur,cur,mod);
    	}
    	return ret;
    }
    
    namespace Pollard_Rho
    {
    	const int N = 15;
    	const int LGM = 64;
    	llong fc[LGM+2];
    	llong a[N+2];
    	llong m;
    	int n;
    	llong ans;
    	llong quickmul(llong x,llong y,llong mod=P)
    	{
    		llong tmp=(x*y-(llong)((long double)x/mod*y+1.0e-8)*mod)%mod;
    		return tmp<0 ? tmp+mod : tmp;
    	}
    	llong quickpow(llong x,llong y,llong mod=P)
    	{
    		llong cur = x,ret = 1ll;
    		for(int i=0; y; i++)
    		{
    			if(y&(1ll<<i)) {ret = quickmul(ret,cur,mod)%mod; y-=(1ll<<i);}
    			cur = quickmul(cur,cur,mod);
    		}
    		return ret;
    	}
    	llong gcd(llong x,llong y) {return y==0 ? x : gcd(y,x%y);}
    	llong absl(llong x) {return x>=0 ? x : -x;}
    	llong ssrand(llong x,llong c,llong y) {return (quickmul(x,x,y)+c)%y;}
    	bool Miller_Rabin(llong x)
    	{
    		if(x==1) return false;
    		if(x==2) return true;
    		if((x&1)==0) return false;
    		llong y = x-1,t = 0ll;
    		while((y&1)==0) y>>=1,t++;
    		for(int i=1; i<=5; i++)
    		{
    			llong bas = rand()%(x-1)+1;
    			llong cur = quickpow(bas,y,x);
    			for(int j=1; j<=t; j++)
    			{
    				llong tmp = quickmul(cur,cur,x);
    				if(tmp==1 && cur!=1 && cur!=x-1) return false;
    				cur = tmp;
    			}
    			if(cur!=1) return false;
    		}
    		return true;
    	}
    	llong pollard_rho(llong x,llong c)
    	{
    		llong i = 1,k = 2;
    		llong y = rand()%(x-1)+1; llong t = y;
    		while(true)
    		{
    			i++;
    			y = ssrand(y,c,x);
    			llong d = gcd(absl(t-y),x);
    			if(d>1 && d<x) return d;
    			if(t==y) return x;
    			if(i==k)
    			{
    				t = y;
    				k<<=1;
    			}
    		}
    	}
    	void factorize(llong x,llong c)
    	{
    		if(x==1) return;
    		if(Miller_Rabin(x))
    		{
    			n++; fc[n] = x;
    			return;
    		}
    		llong p = x,k = c;
    		while(p>=x) p = pollard_rho(p,c--);
    		factorize(p,k); factorize(x/p,k);
    	}
    	void Factorize(llong _m)
    	{
    		m = _m;
    		n = 0;
    		factorize(m,120);
    		sort(fc+1,fc+n+1);
    		pfac.clear();
    		for(int i=1; i<=n; i++)
    		{
    			if(fc[i]==fc[i-1]) {pfac[pfac.size()-1].second++;}
    			else {pfac.push_back(mkpr(fc[i],1));}
    		}
    	}
    }
    
    llong n,m;
    llong ans;
    
    void dfs(int pos,llong x,llong coe)
    {
    	if(pos==pfac.size())
    	{
    		if((x&1ll) && (!((n/x)&1ll))) {return;}
    		llong tmp = quickmul(coe,quickmul(quickpow(m,(x+1)>>1),(x&1)?x:(x>>1)));
    		ans = (ans+tmp)%P;
    		return;
    	}
    	for(int i=0; i<=pfac[pos].second; i++)
    	{
    		dfs(pos+1,x,i==pfac[pos].second?coe:quickmul(coe,(P+1-pfac[pos].first%P)));
    		x = x*pfac[pos].first;
    	}
    }
    
    int main()
    {
    	srand(time(NULL));
    	int T; scanf("%d",&T);
    	while(T--)
    	{
    		scanf("%lld%lld%lld",&n,&m,&P);
    		Pollard_Rho::Factorize(n);
    //		for(int i=0; i<pfac.size(); i++) printf("(%lld,%lld) ",pfac[i].first,pfac[i].second); puts("");
    		ans = 0ll;
    		dfs(0,1ll,1ll);
    		printf("%lld
    ",ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    自我介绍 Self Introduction
    HDU1864 最大报销额
    HDU2955 Robberies
    Sicily 1509. Rails
    Sicily 1031. Campus
    Sicily 1090. Highways
    Sicily 1034. Forest
    Sicily 1800. Sequence
    Sicily 1150. 简单魔板
    CodeVS4919 线段树练习4
  • 原文地址:https://www.cnblogs.com/suncongbo/p/11528825.html
Copyright © 2011-2022 走看看