转自:http://www.cnblogs.com/kevince/p/3887827.html

首先声明一下,这里的规律指的是循环,即找到最小循环周期。

这么一说大家心里肯定有数了吧,“不就是next数组性质的应用嘛”,没错,正是如此。

在ACM的比赛中有些时候会遇到一些题目,可以或必须通过找出数据的规律来编写代码,这里我们专门来讨论下 如何运用KMP中next数组的性质 来寻找一个长数组中的最小循环周期。

先来看一道题

ZOJ 3785

What day is that day?


Time Limit: 2 Seconds      Memory Limit: 65536 KB

It's Saturday today, what day is it after 11 + 22 + 33 + ... + NN days?

Input

There are multiple test cases. The first line of input contains an integer T indicating the number of test cases. For each test case:

There is only one line containing one integer N (1 <= N <= 1000000000).

Output

For each test case, output one string indicating the day of week.

Sample Input

  1. 2
  2. 1
  3. 2

Sample Output

  1. Sunday
  2. Thursday

Hint

A week consists of Sunday, Monday, Tuesday, Wednesday, Thursday, Friday and Saturday.

题目的大意是知道今天是周六,让你求 f = 11 + 22 + 33 + ... + NN 这么多天之后是星期几。

也就是求f % 7对于每个输入的N的值。这题在网上一搜题解,都说是打表找规律,当然这题有两种找法,一是对于每个ii  % 7 的值都找规律。

这里我们打表可知 前100个值如下所示

1 4 6 4 3 1 0 1 1 4 2 1 6 0 1 2 5 1 5 1 0 1 4 1 4 4 6 0 1 1 3 2 6 1 0 1 2 2 1 2 6 0 1 4 6 4 3 1 0 1 1 4 2 1 6 0 1 2 5 1 5 1 0 1 4 1 4 4 6 0 1 1 3 2 6 1 0 1 2 2 1 2 6 0 1 4 6 4 3 1 0 1 1 4 2 1 6 0 1 2

有一种找规律的方法是当有数字等于第一个数的时候做个标记,再人工判断是否能够构成一个循环。

不可否认的,对于周期较短的一组数字这样找周期并不难,可是如果周期大到数百数千甚至数万时,靠这种方法找周期恐怕是杯水车薪。

当时我就迷茫在了这一长串的数字中不知所措,猛然想起前不久看过的KMP中next数组的性质,当即想到了用KMP求最小重复子串长度的方法,于是脑洞大开……

该性质为:令j=leni-next[i],如果i%j==0且i/j>1,j就是Pi的最小循环节( Pi表示文本串的前i个字符,leni表示该字符串的长度,一般表示为leni = i + 1)

还有一种找规律的方法是直接对 f % 7 的值进行打表找规律,按照上述方法找到的周期为294,下面要做的就很简单了~

  1. #include <iostream>
  2. #include<cstdio>
  3. #include<cstdlib>
  4. #include<cstring>
  5. #include<algorithm>
  6. #include<vector>
  7. #define N 605
  8. #define M 200
  9. #define ll long long
  10. using namespace std;
  11. int i,j;
  12. int T;
  13. int l;
  14. int a[N],sum[N];
  15. char s[N];
  16. int next[N];
  17. int fun(int n)
  18. {
  19. int re = ;
  20. for(int i=;i<=n;i++){
  21. re*=n;
  22. re%=;
  23. }
  24. return re;
  25. }
  26. void ini()
  27. {
  28. a[]=sum[]=;
  29. a[]=sum[]=;
  30. s[]='';
  31. s[]='';
  32. for(i=;i<=N-;i++){
  33. a[i]=fun(i);
  34. sum[i]+=a[i]+sum[i-];
  35. sum[i]%=;
  36. s[i]=sum[i]+'';
  37. }
  38. s[i]='\n';
  39. //printf("%s\n",s);
  40. // for(i=1;i<=M;i++){
  41. // printf(" %d %d %d\n",i,a[i],sum[i]);
  42. // printf(" %d",sum[i]);
  43. //}
  44. return;
  45. }
  46.  
  47. void ini2()
  48. {
  49. int j = -, i = ;
  50. next[] = -;
  51. while(i < N-)
  52. {
  53. if(j == - || s[i] == s[j])
  54. {
  55.  
  56. i++;
  57. j++;
  58. next[i] = j;
  59. }
  60. else
  61. {
  62. j = next[j];
  63. }
  64. }
  65. }
  66.  
  67. void ini3()
  68. {
  69. for(int i = ; i <= N-; ++i)
  70. {
  71. int length = i - next[i]; //循环节的长度
  72. if(i != length && i % length == ) //如果有多个循环
  73. {
  74. printf("%d %d\n", i, i / length);
  75. break;
  76. }
  77.  
  78. }
  79. }
  80.  
  81. int main()
  82. {
  83. int x;
  84. int ans;
  85. ini();
  86. //ini2();
  87. // ini3();
  88. //freopen("data.txt","r",stdin);
  89. scanf("%d",&T);
  90. //while(scanf("%d",&n)!=EOF)
  91. while(T--)
  92. {
  93. scanf("%d",&x);
  94. ans=sum[x%];
  95. if(ans==) printf("Saturday\n");
  96. else if(ans==) printf("Sunday\n");
  97. else if(ans==) printf("Monday\n");
  98. else if(ans==) printf("Tuesday\n");
  99. else if(ans==) printf("Wednesday\n");
  100. else if(ans==) printf("Thursday\n");
  101. else if(ans==) printf("Friday\n");
  102. }
  103. return ;
  104. }

后来又练了一次,用了map

4172110 2016-03-15 15:26:39 Accepted 3785 C++ 820 280 njczy2010
  1. #include <iostream>
  2. #include <cstdio>
  3. #include <map>
  4. #include <cstring>
  5. #include <algorithm>
  6. #include <cmath>
  7. #include <string>
  8.  
  9. using namespace std;
  10.  
  11. #define N 1005
  12. #define ll long long
  13. #define mod 7
  14.  
  15. int TT;
  16. int n;
  17. int s[N];
  18. int next[N];
  19. map<int,string> mp;
  20.  
  21. void get_next()
  22. {
  23. int i,j;
  24. i = ;
  25. j = -;
  26. next[] = -;
  27. while(i<N)
  28. {
  29. if(j == - || s[i] == s[j]){
  30. i++;j++;next[i] = j;
  31. }
  32. else{
  33. j = next[j];
  34. }
  35. }
  36. }
  37.  
  38. int quickpow(int x,int n)
  39. {
  40. int re = ;
  41. while(n)
  42. {
  43. if(n&){
  44. re = (re * x) % mod;
  45. }
  46. n /= ;
  47. x = (x * x) % mod;
  48. }
  49. return re;
  50. }
  51.  
  52. void fi()
  53. {
  54. int i;
  55. for(i = ;i < N;i++){
  56. int length = i - next[i]; //循环节的长度
  57. if(i != length && i % length == ) //如果有多个循环
  58. {
  59. printf("%d %d %d\n", i, length, i / length);
  60. break;
  61. }
  62. }
  63. }
  64.  
  65. void ini()
  66. {
  67. int i;
  68. s[] = ;
  69. for(i = ;i < N;i++){
  70. s[i] = (s[i - ] + quickpow(i,i) )%mod;
  71. }
  72. mp[] = "Saturday";
  73. mp[] = "Sunday";
  74. mp[] = "Monday";
  75. mp[] = "Tuesday";
  76. mp[] = "Wednesday";
  77. mp[] = "Thursday";
  78. mp[] = "Friday";
  79. //get_next();
  80. //fi();
  81. //
  82. }
  83.  
  84. int main()
  85. {
  86. //freopen("in.txt","r",stdin);
  87. //freopen("out.txt","w",stdout);
  88. ini();
  89. scanf("%d",&TT);
  90. while(TT--){
  91. //while(scanf("%d",&n)!=EOF){
  92. scanf("%d",&n);
  93. cout << mp[ s[ n% ] ] << endl;
  94. }
  95. return ;
  96. }

【ZOJ】3785 What day is that day? ——KMP 暴力打表找规律的更多相关文章

  1. 【ZOJ】3785 What day is that day? ——浅谈KMP在ACM竞赛中的暴力打表找规律中的应用

    转载请声明出处:http://www.cnblogs.com/kevince/p/3887827.html    ——By Kevince 首先声明一下,这里的规律指的是循环,即找到最小循环周期. 这 ...

  2. ZOJ 3622 Magic Number 打表找规律

    A - Magic Number Time Limit:2000MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu Subm ...

  3. zoj 3785 What day is that day? (打表找规律)

    题目 思路:比赛的时候有想过找循环节,但是,打表打错了. 后来,看着过了挺多人,就急了, 看了一下别人的时间 耗时都挺长的,就以为不是找规律, 没想到真是找规律,不过,这个题的数据可能挺大的. AC代 ...

  4. zoj 3629 Treasure Hunt IV 打表找规律

    H - Treasure Hunt IV Time Limit:2000MS     Memory Limit:65536KB     64bit IO Format:%lld & %llu ...

  5. 【ARC077F】SS kmp+打表找规律

    Description ​ 如果某个串可以由两个一样的串前后连接得到,我们就称之为"偶串".比如说"xyzxyz"和"aaaaaa"是偶串, ...

  6. ZOJ 3785 What day is that day?(今天是星期几?)

    Description 题目描述 It's Saturday today, what day is it after 11 + 22 + 33 + ... + NN days? 今天是星期六,11 + ...

  7. ZOJ 3587 Marlon&#39;s String 扩展KMP

    链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3587 题意:给出两个字符串S和T.S,T<=100000.拿出 ...

  8. zoj 3785 What day is that day?

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5272 打表找规律. #include <cstdio> #incl ...

  9. ZOJ 3785 What day is that day?(数论:费马小定理)

    What day is that day? Time Limit: 2 Seconds      Memory Limit: 65536 KB It's Saturday today, what da ...

随机推荐

  1. Java IO 之 File 的创建、重命名与遍历

    File表示存储设备上的一个文件或目录,使用方式查看API即可,比较简单 package org.zln.io.file; import java.io.File; /** * Created by ...

  2. jQuery下拉列表二级联动插件

    jQuery下拉列表二级联动插件的视图代码: <!doctype html> <html lang="en"> <head> <meta ...

  3. JDBC连接数据库的过程

    以连接MySQL为例: (1)加载MySQL数据库连接的驱动程序.到MySQL官网下载该驱动程序jar包,然后把包复制到WEB-INF/lib目录下,则JDBC会调用Class.forName()方法 ...

  4. 如何在Javascript中利用封装这个特性

    对于熟悉C#和Java的兄弟们,面向对象的三大思想(封装,继承,多态)肯定是了解的,那么如何在Javascript中利用封装这个特性呢? 我们会把现实中的一些事物抽象成一个Class并且把事物的属性( ...

  5. 怎么把linux的磁盘映射到windows上

    步骤如下: 右击如下的computer: 然后选择:Map network drive... 然后在下图按图中所示操作: 最后成功如下图所示:

  6. bzoj 2525 [Poi2011]Dynamite 二分+树形dp

    [Poi2011]Dynamite Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 270  Solved: 138[Submit][Status][D ...

  7. 修改firefox默认下载路径

    菜单栏---编辑---首选项--在常规页就可以看到下载设置了

  8. Spring 中 AbstractExcelView 支持根据模板生成Excel文件. 通过设置 view 的 URL 属性指定模板的路径

     注意:1. 模板需放在 WEB-INF 目录下2. 指定模板路径时不需要添加扩展名, Spring将自动添加 .xls 到URL 属性中.3. 在指定URL前需先设置 view 的 Applicat ...

  9. checkbox和后面文字无法居中对齐的解决方案

    制作前端页面时,表单的页面中都存在表单元素与提示文字无法对齐的问题.下面是针对这一问题的解决方案: 先上结果图看效果,吼吼~ 最上面两个是经过css处理后的效果,已经居中对齐了哦~,最后一个是没有处理 ...

  10. NYOJ 973 天下第一 (最短路)

    题目链接 描述 AC_Grazy一直对江湖羡慕不已,向往着大碗吃肉大碗喝酒的豪情,但是"人在江湖漂,怎能 不挨刀","人在江湖身不由己",如果自己的武功太差,在 ...