2016"百度之星" - 初赛(Astar Round2A)1001 All X(HDU5690)——找循环节|快速幂
Posted Storm_Spirit
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2016"百度之星" - 初赛(Astar Round2A)1001 All X(HDU5690)——找循环节|快速幂相关的知识,希望对你有一定的参考价值。
一个由m个数字x组成的新数字,问其能否mod k等于c。
先提供第一种思路,找循环节。因为每次多一位数都是进行(t*10+x)mod k(这里是同余模的体现),因为x,k都确定,只要t再一样得到的答案一定一样。所以在一步一步中进行时一旦出现了一个之前出现过的数字,那么很显然后面就要开始进行循环了。找出这个循环节,然后把m放到这个循环节里头就行(这里的说法有问题,见下文的第二点)。
但是这里有两个要注意的地方,第一是只有当前出现的数一样才能保证下一个出现的数一样,而并不代表着,当前的数一样,得到它的数就一样,因此,第一个数并不一定参与循环。不妨举个最简单的例子,这一系列的数字是,3,4,5,6,4,5,6,4,5,6。。。第一个3并不参与循环。其实也好理解,一个分数,其分母和分子一样,所以也相当于一直进行同样的操作,最后一定会处于循环状态(不循环的话视作一直0循环),但是很显然的第一位小数不一定是参与循环的部分。
第二点是,基于上一点,m如果较小的话不一定处于循环节内,那么就没办法把它放到循环节里头,那么直接从1算到m即可。
下面给出的学长的代码,很巧妙的解决了所有的问题:
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 using namespace std; 5 typedef long long LL; 6 const int N = 10000 + 5; 7 LL pos[N]; 8 LL x, m, k, c; 9 int main(){ 10 int T; 11 int cas = 1; 12 scanf("%d", &T); 13 while(T --){ 14 memset(pos, -1, sizeof(pos)); 15 scanf("%I64d%I64d%I64d%I64d", &x, &m, &k, &c); 16 printf("Case #%d:\\n", cas ++); 17 int tmp = 0; 18 LL d; 19 for(LL i = 1; i <= m; i ++){ 20 tmp = tmp * 10 + x; 21 tmp %= k; 22 if(pos[tmp] == -1){ 23 pos[tmp] = i; 24 }else{ 25 d = i - pos[tmp]; 26 i += (m - i) / d * d; 27 if(i > m) i -= d; 28 for(LL j = i+1; j <= m; j ++){ 29 tmp = tmp * 10 + x; 30 tmp %= k; 31 } 32 break; 33 } 34 } 35 if(tmp == c) puts("Yes"); 36 else puts("No"); 37 } 38 }
第二种方法是快速幂,很巧妙,直接搬运别人的博客了:http://www.cnblogs.com/inmoonlight/p/5515538.html 直接没几行代码就没了,也是厉害。。
以上是关于2016"百度之星" - 初赛(Astar Round2A)1001 All X(HDU5690)——找循环节|快速幂的主要内容,如果未能解决你的问题,请参考以下文章
2016"百度之星" - 初赛(Astar Round2B)
2016"百度之星" - 初赛(Astar Round2A)
2016"百度之星" - 初赛(Astar Round2B)
2016"百度之星" - 初赛(Astar Round2A)