版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_27121257/article/details/82627444
传送门:洛谷 P1050
题目描述
乐乐是一个聪明而又勤奋好学的孩子。他总喜欢探求事物的规律。一天,他突然对数的正整数次幂产生了兴趣。
众所周知,
的正整数次幂最后一位数总是不断的在重复
我们说
的正整数次幂最后一位的循环长度是
(实际上
的倍数都可以说是循环长度,但我们只考虑最小的循环长度)。类似的,其余的数字的正整数次幂最后一位数也有类似的循环现象:
这时乐乐的问题就出来了:是不是只有最后一位才有这样的循环呢?对于一个整数nn的正整数次幂来说,它的后k位是否会发生循环?如果循环的话,循环长度是多少呢?
注意:
1. 如果
的某个正整数次幂的位数不足k,那么不足的高位看做是
。
2. 如果循环长度是
,那么说明对于任意的正整数
的
次幂和
次幂的最后
位都相同。
分析
一道头痛的凶残的数学题,首先看看数据范围,有点头痛(就不能好好地打打暴力么),加上高精度也绝对是要T了的。
对此考虑用数学来补救
在保证有解的情况下,若后
位的循环长度为
,则后
位的长度必定为
,其中
.因此,我们可以考虑从个位数开始逐步往前递推,每次只需求出对应的
即可。
寻找
:令原数为
,若寻找后
的长度,我们只需要找到最小的
,使之满足
,对此,先求出
,然后枚举k判断即可
判断有解:经证明(/逃,知道的
,请留个言,谢谢),
,超出范围则无解
代码
#include <cstdio>
#include <cstdlib>
#include <cstring>
#define IL inline
//#define open(s) freopen(s".in","r",stdin); freopen(s".out","w",stdout);
//#define close fclose(stdin); fclose(stdout);
using namespace std;
IL int read()
{
char c = getchar();
int sum = 0 ,k = 1;
for(;'0' > c || c > '9'; c = getchar())
if(c == '-') k = -1;
for(;'0' <= c && c <= '9'; c = getchar()) sum = sum * 10 + c - '0';
return sum * k;
}
int m;
IL int min_(int x, int y) { return x < y ? x : y; }
IL int max_(int x, int y) { return x > y ? x : y; }
struct Bigint
{
int size;
int num[105];
IL Bigint()
{
size = 0;
memset(num, 0, sizeof(num));
}
Bigint operator * (const Bigint &b) //高精*高精,限制了位数
{
Bigint c;
for(int i = 1, p, r; i <= size; ++i)
{
p = i;
r = 0;
for(int j = 1; j <= b.size && p <= m; ++j, ++p)
{
r += c.num[p] + num[i] * b.num[j];
c.num[p] = r % 10;
r /= 10;
}
for(; p <= m && r; ++p, r /= 10)
{
r += c.num[p];
c.num[p] = r % 10;
}
}
c.size = min_(size + b.size, m);
for(; !c.num[c.size]; --(c.size));
return c;
}
Bigint operator * (const int b) //高精*单精,仅供ans使用
{
Bigint c;
int s = size, r = 0;
for(int i = 1; i <= size; ++i)
{
r += b * num[i];
c.num[i] = r % 10;
r /= 10;
}
for(; r; r /= 10)
c.num[++s] = r % 10;
c.size = s;
return c;
}
IL bool is_same(int t, const Bigint &b)//判断后t位相等
{
for(int i = min_(t, max_(size, b.size)); i; --i)
if(num[i] != b.num[i])
return 0;
return 1;
}
IL void wri()
{
for(int i = size; i; --i)
printf("%d", num[i]);
printf("\n");
}
}k, ans;
char num[105];
int base[10] = {0, 1, 4, 4, 2, 1, 1, 4, 4, 2};//预处理个位情况
IL void power(int t)//好吧,简单的循环而已
{
if(t == 1) return ;
Bigint tmp = k;
for(--t; t; --t) k = k * tmp;
}
IL void check(Bigint p, int len)//求后len位的解
{
Bigint x = p;
for(int t = 1; t <= 10; ++t)
{
x = x * k;
if(p.is_same(len, x))
{
ans = ans * t;
power(t);
return ;
}
}
ans.size = 1;
ans.num[1] = -1;
}
int main()
{
//open("circle")
scanf(" %s %d", num + 1, &m);
int len = strlen(num + 1);
k.size = m < len ? m : len;
for(int i = 1; i <= k.size; ++i)
k.num[i] = num[len - i + 1] - '0';
Bigint p;
p.size = 1; p.num[1] = num[len] - '0';
ans.size = 1; ans.num[1] = base[num[len--] - '0'];
power(ans.num[1]);
for(int i = 2; i <= m; ++i)
{
++(p.size);
if(len) p.num[p.size] = num[len--] - '0';
check(p, i);
if(ans.num[1] == -1) break;
}
ans.wri();
//close
return 0;
}