You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

72 lines
2.8 KiB

2 years ago
#include <bits/stdc++.h>
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<K的限制
for (int i = 0; i < K; i++) {
t += c[i]; // 进位与当前位置的和
a[i] = t % 10; // 余数保留下来
t /= 10; // 进位
}
}
int main() {
string s; // 这里之所以用string类型是为了照顾高精度同学
cin >> 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;
}