题目
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)}
2k≡1(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;
}