gmoj 6832. 2020.10.24【NOIP提高A组】world 题解

题目

https://gmoj.net/senior/#main/show/6832

题解

这题我发现模拟1的位置变换就可以了,然后打出了40分的表。然而接下来就想不到了……

可以发现第 i 个位置上的数在变换一次之后会跑到 2 i m o d    ( n + 1 ) 2i\mod (n+1) 2imod(n+1)的位置上去,那么1在变换了k次之后就会在 2 k m o d    ( n + 1 ) 2^k\mod (n+1) 2kmod(n+1)上,若此时1回到了1,就有 2 k ≡ 1 ( m o d ( n + 1 ) ) 2^k\equiv 1\pmod{(n+1)} 2k1(mod(n+1))
若n是最小的k,则n合法。

欧拉定理 a φ ( m ) ≡ 1 ( m o d m ) , gcd ⁡ ( a , m ) = 1 a^{\varphi(m)}\equiv 1\pmod{m}\quad,\gcd(a,m)=1 aφ(m)1(modm),gcd(a,m)=1 2 φ ( n + 1 ) ≡ 1 ( m o d ( n + 1 ) ) 2^{\varphi(n+1)}\equiv 1\pmod{(n+1)} 2φ(n+1)1(mod(n+1))

若n+1不是质数, φ ( n + 1 ) < n \varphi(n+1)< n φ(n+1)<n,故要满足n+1为质数。
但此时n不一定是最小的k,还需暴力枚举判断,过不了。

考虑优化。因为n不是最小的k时,1必定是转了若干个循环的,而最小的循环长度必定是n的因数,因此这个因数的其它倍数也会满足条件。

把n分解质因数,令 n = ∏ p i q i n=\prod p_i^{q_i} n=piqi,如果n不是最小的k,那么必定有 n p i \frac{n}{p_i} pin满足条件。

因为一个数的不同质因子个数小于等于8,因此可以通过本题。

CODE

#include<cstdio>
using namespace std;
typedef long long ll;
#define N 10000005
int pri[700005],p[N];bool b[N];
inline int pow(int x,int y,int p)
{
    
    
	int s=1;
	while(y)
	{
    
    
		if(y&1) s=1LL*s*x%p;
		x=1LL*x*x%p,y>>=1;
	}
	return s;
}
int main()
{
    
    
	freopen("world.in","r",stdin);
	freopen("world.out","w",stdout);
	ll sum=0;int A,tmp,j;
	scanf("%d",&A);
	for(int i=2;i<N;++i)
	{
    
    
		if(!b[i]) pri[++pri[0]]=i,p[i]=i;
		for(int j=1;j<=pri[0]&&i*pri[j]<N;++j)
		{
    
    
			b[i*pri[j]]=1,p[i*pri[j]]=pri[j];
			if(i%pri[j]==0) break;
		}
	}
	for(int i=2;i<=A;++i) if(!b[i+1])
	{
    
    
		tmp=i;
		while(tmp>1)
		{
    
    
			j=p[tmp];
			if(pow(2,i/j,i+1)==1) break;
			while(tmp%j==0) tmp/=j;
		}
		if(tmp==1) sum+=i;
	}
	A>>=1,printf("%.5LF\n",sum/(long double)A);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/huangzihaoal/article/details/109320191
今日推荐