#include using namespace std; const int N = 110; int K; // 求最后K位的循环节长度是多少 int a[N]; // 原始数组 int b[N]; // 工作数组 int d[N] = {1}; // 次数,也就是答案 // 高精乘高精,限长K(K<=100,不是很大) void mul(int a[], int b[]) { int t = 0; int c[N] = {0}; for (int i = 0; i < K; i++) for (int j = 0; j < K; j++) if (i + j < K) c[i + j] += a[i] * b[j]; // 防止越界,需要加上i+j> s >> K; // 求最后k个长度的循环节长度是多少 // 放入高精度计算数组,注意是倒着放的,下标从0开始 for (int i = s.size() - 1; i >= 0; i--) a[s.size() - 1 - i] = s[i] - '0'; for (int i = 0; i < K; i++) { // 执行K轮,从后往前,每轮固定一个尾部数字 int st[11] = {0}; // 某个数字是不是出现过,桶 memcpy(b, a, sizeof a); // b数组初始化 int j; for (j = 1; j <= 10; j++) { // 最多执行10次 mul(b, a); // 开始乘a // 对于高精度数组而言,头部即数字尾部 // 随着轮次的增加,我们希望检查的位置也发生了变化,位置下标为i // 如果当前计算的结果中,当前的计算位置,出现与原数字一样的数字,那么就是找到了循环节,此时的j就是我们想要收集的 if (b[i] == a[i]) break; // 如果某个数字重复出现,却一直没有和原始的一样,表示它自己的循环轨迹和原始的不一样,永远也不可以一样了,无解 if (st[b[i]]) { puts("-1"); exit(0); }; st[b[i]] = 1; // 记录出现过的数字 } // ① 累计次数 int c[N] = {j}; // 需要乘的次数,这里有用高精度乘高精度模拟高精度乘低精度 // 注意:即使j=10,上面的高精度乘法依然是有效的,因为在高精度乘法的内部采用的是模10进位的办法 mul(d, c); // 将次数累乘起来 // ② 变更乘数 memcpy(b, a, sizeof a); // 重新装载原始数字 for (int k = 1; k < j; k++) mul(b, a); // 反复乘j-1次 memcpy(a, b, sizeof b); // a升级了 } int dl = K; while (dl > 0 && d[dl] == 0) dl--; // 去除前导零 for (int i = dl; i >= 0; i--) cout << d[i]; // 逐位输出 return 0; }