ABC222 G - 222(数论)
ABC222 G - 222
解题思路
首先看到题目我们发现,对于 \(99983\) 和 \(2\) 等数字答案都等于这个数本身 \(-1\)。我们又发现这些数是质数,非常自然想到费马小定理。但是赛时我只想到了这一点,并没有把费马小定理推广到欧拉函数上。而这是解题的关键。
我们知道,对于任意的 \(x\),对于\(\gcd(a,x)=1\)有:
这就是欧拉定理。问题是我们如何与这道题联系起来呢?我们其实很容易对于一个数 \(x=2\cdot k\ \ (k\in Z)\) 若有 \(x\mid 222\dots222\),一定有 \(k\mid 111\dots 111\)。这有什么用呢?我们可以在想一步,若对于 \(x=2\cdot k+1\ \ (k\in Z)\) 我们有 \(x\mid 111\dots 111\)。
然后怎么办?我们尝试找一下 \(111\dots 111\) 的性质,发现它其实可以表示为 \(\frac{10^n-1}9\) 的形式。这好像和欧拉定理可以联系上了。同上面的变化方式,我们可以将 \(x\) 或者 \(k\) 乘上 \(9\),使得得到的新数 \(x'\) 满足 \(x'\mid 10^n-1\)。
是不是柳暗花明又一村了?我们可以进一步推柿子。
那我们就要找最小的满足条件的 \(n\)。由欧拉定理,\(\varphi(x')\) 一定满足条件(只要 \(\gcd(x',10)=1\))。那么我们输出 \(\varphi(x')\) 就可以了吗?
达咩达咩。
我们发现对于 \(x=37\),\(n=3\) 就满足条件。也就是说,\(\varphi(x')\) 不一定是最小的满足条件的数。满足条件的最小的 \(n\) 一定是 \(\varphi(x')\) 的约数。
我们 \(O(\sqrt x)\) 求出 \(\varphi(x)\),再用 \(O(\sqrt {\varphi(x)})\) 算出答案即可。
总时间复杂度为\(O(T \sqrt n)\)。问题解决。
代码
//Don't act like a loser.
//This code is written by huayucaiji
//You can only use the code for studying or finding mistakes
//Or,you'll be punished by Sakyamuni!!!
#include<bits/stdc++.h>
#define int long long
//忽略这个 @zdm
using namespace std;
int read() {
char ch=getchar();
int f=1,x=0;
while(ch<'0'||ch>'9') {
if(ch=='-')
f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9') {
x=x*10+ch-'0';
ch=getchar();
}
return f*x;
}
int n;
int qpow(int x,int y,int m) {
int ret=1;
while(y) {
if(y&1) {
ret=ret*x%m;
}
x=x*x%m;
y>>=1;
}
return ret;
}
int phi(int x) {
int ret=x;
for(int i=2;i*i<=x;i++) {
if(x%i==0) {
ret=ret/i*(i-1);
}
while(x%i==0) {
x/=i;
}
}
if(x>1) {
ret=ret/x*(x-1);
}
return ret;
}
int check(int x,int phix) {
int ans=x+1;
for(int i=1;i*i<=phix;i++) {
if(phix%i==0) {
if(qpow(10,i,x)==1) {
return i;
//若这个 i 满足条件一定是最优的
//直接返回
}
else if(qpow(10,phix/i,x)==1) {
ans=phix/i;
//否则要再取 min(直接更新即可,因为这个值单调减)
}
}
}
return ans==x+1? -1:ans;
}
signed main() {
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
int t=read();
while(t--) {
int x=read();
if(x&1) {
x=x*9;//转换 x->x'
}
else {
x=x/2*9;
}
cout<<check(x,phi(x))<<endl;
}
//fclose(stdin);
//fclose(stdout);
return 0;
}