转载请声明出处:http://www.cnblogs.com/kevince/p/3887827.html    ——By Kevince

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

这么一说大家心里肯定有数了吧,“不就是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

2
1
2

Sample Output

Sunday
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)

关键代码如下:

/*注:int next[]为next数组,int arr[]为要找规律的数组,len为数组长度*/
next[] = ;
for(int i = , q = ; i < len; i++){
while(q > && arr[i] != arr[q])
q = next[q-];
if (arr[i] == arr[q])
q++;
next[i] = q;
if (q != && (i + ) % (i + - q) == ){
printf("%d\n", i+-q);
break;
}
}

可以求出最小周期为42。

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

AC代码如下:

 #include <cstdio>

 const char day[][] = {"Saturday", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday"};
int s[]; int work(int n)
{
int sum = ;
for(int i = ; i <= n; i++){
sum = sum * n;
sum %= ;
}
return sum;
} void init()
{
s[] = ;
for(int i = ; i <= ; i++){
s[i] = s[i-] + work(i);
s[i] %= ;
}
} int main()
{
int T;
int n;
init();
scanf("%d", &T);
while(T--){
scanf("%d", &n);
n %= ;
printf("%s\n", day[ s[n]]);
}
return ;
}

---------------------------------------------------------我是分割线--------------------------------------------------------------

自从上次大开脑洞之后,今天又遇到了一道题,POJ 3070。

题目的大意是让你求第n个斐波那契数的后四位是多少,题目的本意考察的是矩阵快速幂,可是暴力打表又有何不可呢?遂打表用KMP查询,找到周期为15000,顺利水过了这题~

嗯,这篇文章只是跟大家分享一下自己偶然发现的KMP在竞赛中一种用法,在有些题目中使用不免有投机取巧之嫌(就像POJ 3070 ╮(╯▽╰)╭),不过不管投机不投机,只要能AC,就是好方法。O(∩_∩)O哈哈~ 开个玩笑,若有不足之处,还请各位指正。

【ZOJ】3785 What day is that day? ——浅谈KMP在ACM竞赛中的暴力打表找规律中的应用的更多相关文章

  1. 【ZOJ】3785 What day is that day? ——KMP 暴力打表找规律

    转自:http://www.cnblogs.com/kevince/p/3887827.html 首先声明一下,这里的规律指的是循环,即找到最小循环周期. 这么一说大家心里肯定有数了吧,“不就是nex ...

  2. 浅谈Python在信息学竞赛中的运用及Python的基本用法

    浅谈Python在信息学竞赛中的运用及Python的基本用法 前言 众所周知,Python是一种非常实用的语言.但是由于其运算时的低效和解释型编译,在信息学竞赛中并不用于完成算法程序.但正如LRJ在& ...

  3. ZOJ 3622 Magic Number 打表找规律

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

  4. 浅谈c#的三个高级参数ref out 和Params C#中is与as的区别分析 “登陆”与“登录”有何区别 经典SQL语句大全(绝对的经典)

    浅谈c#的三个高级参数ref out 和Params   c#的三个高级参数ref out 和Params 前言:在我们学习c#基础的时候,我们会学习到c#的三个高级的参数,分别是out .ref 和 ...

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

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

  6. 浅谈Xcode5和Xcode7在系统创建的文件夹和文件中的区别

    *:first-child { margin-top: 0 !important; } body > *:last-child { margin-bottom: 0 !important; } ...

  7. 浅谈KMP算法及其next[]数组

    KMP算法是众多优秀的模式串匹配算法中较早诞生的一个,也是相对最为人所知的一个. 算法实现简单,运行效率高,时间复杂度为O(n+m)(n和m分别为目标串和模式串的长度) 当字符串长度和字符集大小的比值 ...

  8. [原创]浅谈JAVA在ACM中的应用

    由于java里面有一些东西比c/c++方便(尤其是大数据高精度问题,备受广大ACMer欢迎),所以就可以灵活运用这三种来实现编程,下面是我自己在各种大牛那里总结了一些,同时加上自己平时遇到的一些jav ...

  9. 浅谈PipelineDB系列一: Stream数据是如何写到Continuous View中的

    PipelineDB Version:0.9.7 PostgreSQL Version:9.5.3 PipelineDB的数据处理组件: 从上图来看主要就是pipeline_streams,strea ...

随机推荐

  1. invesments 第三章 上

    1. How firms issue securities: 公司如何发行股票 A.       primary market: 新的股票,债券和其他的证券第一次发行的market B.        ...

  2. Linux下查看Web服务器当前的并发连接数和TCP连接状态

    对于web服务器(Nginx.Apache等)来说,并发连接数是一个比较重要的参数,下面就通过netstat命令和awk来查看web服务器的并发连接数以及TCP连接状态. $ netstat -n | ...

  3. No.26

    "信是未见之事的实底,是所望之事的确据".

  4. 部分和问题(dfs)

    部分和问题 时间限制:1000 ms  |           内存限制:65535 KB 难度:2   描述 给定整数a1.a2........an,判断是否可以从中选出若干数,使它们的和恰好为K. ...

  5. MTK 2G芯片使用联通卡在深圳无法拨打112原因

    2.75G GSM模块在深圳客户这边联调到最后,客户这边遇到各种概率性问题,基本都是对方使用的配件不够好造成的,如天线.SIM卡座等配件. 一旦这些配件不好,就会出现概率性的错误,非常难以复现,所以在 ...

  6. swiftTools

    String+Exten.swift // // String+Exten.swift // swiftTest // // Created by napiao on 15/11/27. // Cop ...

  7. 安装sql server 2008 management studio时,提示升级VS2008 到 SP1

    安装sql server 2008 management studio时,提示错误:此计算机上安装了 Microsoft Visual Studio 2008 的早期版本.请在安装 SQL Serve ...

  8. centos添加sudoers

    CentOS添加sudoers 1.chmod 740 /etc/sudoers 2. ## Allow root to run any commands anywhere     root    A ...

  9. 宏定义 define

    #define kOut -1 用一个字符串代替一个数据 用kOut表示-1(一般开头有一个小写的k) 作用: 1.为了让一些数据有意义 #define kUseId asdjlfdjafa #def ...

  10. UINavigationController  和 UITabBarController

    UINavigationController当设置根控制器的时候,意思就是把根控制器压入栈内,当我们push的时候,我们把下一个控制器压入栈内,当我们pop的时候把上面的控制器的内存释放   UITa ...