2016"百度之星"

  一个由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:
", 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 直接没几行代码就没了,也是厉害。。

原文地址:https://www.cnblogs.com/zzyDS/p/5516651.html