题解:AT_abc222_g [ABC222G] 222
AT_abc222_g [ABC222G] 222 题解分析
思路
题意转化
等价于求最小的
引理部分
引理
引理
变换
不难用两个引理转换题意为:
其中
注意到欧拉定理:
所以:
我们假设
则:
推导得:
由于:
故:
由于
其中
- 若
k_2=0 ,则\varphi(M)=kx ,得到x\mid\varphi(M) 。 - 若
k_2\ne0 ,则\varphi(M)=(k+k_2)x ,得到x\mid\varphi(M) 。
综上所述:
故我们可以暴力枚举
引理推导
引理
设
有:
设
得到:
所以:
由于:
所以又有:
引理
跟上述差不多。
首先设
然后就有:
所以:
代码
时间复杂度
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <stdlib.h>
#include <cstring>
#include <vector>
#define int long long
#define N 100000001
#define M 5761457
using namespace std;
int T;
//bool vis[N];
//int prime[N],phi[N],cnt;
int qpow(int a,int b,int mod) {
int res = 1;
while(b) {
if (b & 1) res = res * a % mod;
a = a * a % mod;
b >>= 1;
}
return res;
}
//void init(int n) {
// phi[1] = 1;
// for (int i = 2;i <= n;i ++) {
// if (!vis[i]) prime[++cnt] = i,phi[i] = i - 1;
// for (int j = 1;j <= cnt && prime[j] * i <= n;j ++) {
// vis[prime[j] * i] = 1;
// if (i % prime[j] == 0) {
// phi[i * prime[j]] = prime[j] * phi[i];
// break;
// }
// phi[i * prime[j]] = phi[prime[j]] * phi[i];
// }
// }
//// cout << cnt << endl;
//// for (int i = 1;i <= cnt;i ++) cout << prime[i] << ' ';
//}
int get_euler(int x) {
int res = x;
for (int i = 2;i * i <= x;i ++)
if (x % i == 0){
while(x % i == 0) x /= i;
res = res / i * (i - 1);
}
if (x > 1) res = res / x * (x - 1);
return res;
}
signed main(){
//int T;
cin >> T;
for (;T--;) {
int x;
scanf("%lld",&x);
int mod = ((x & 1) ? x * 9 : x / 2 * 9),phi = get_euler(mod),res = phi + 1;
for (int i = 1;i * i <= phi;i ++)
if (phi % i == 0) {
// cout << i << ' ' << qpow(10,i,mod) << endl;
if (qpow(10,i,mod) == 1) res = min(res,i);
if (qpow(10,phi / i,mod) == 1) res = min(res,phi / i);
}
if (res == phi + 1) puts("-1");
else printf("%lld\n",res);
}
return 0;
}
感谢管理员的审核,最后一次更改了一些细节。