@2017-2018 ACM-ICPC, Asia Daejeon Regional Contest @Gym 101667I Slot Machines (巧用KMP,next 求循环节)

 

 

题目描述

Slot machines are popular game machines in casinos. The slot machine we are considering has six places where a figure appears. By combination of figures, one may earn or lose money. There are ten kinds of figures, so we will represent a figure with a number between 0 and 9. Then we can use a six-digit number w = w1w2w3w4w5w6 where 0 ≤ w1, w2, w3, w4, w5, w6 ≤ 9 to represent one possible outcome of the slot machine.

Figure I.1. The layout of a slot machine.


Old slot machines were made up with mechanical components, but nowadays they were replaced by PC-based systems. This change made one critical flaw: they are based on pseudo-random number generators and the outcome sequences of a slot machine are periodic. Let T[i] be the i-th outcome of a slot machine. At first, there is a truly random sequence of length k,T[1],T[2],…,T[k]. Then there exists one positive number such that T[i+p] = T[i]for all possible values of i(>k). Once an attacker can find out the exact values of k and p, he or she can exploit this fact to beat the casino by betting a lot of money when he or she knows the outcome with a good combination in advance.

For example, you have first six numbers of outcome sequences: 612534, 3157, 423, 3157, 423, and 3157. Note that we can remove first 0’s. Therefore, 3157 represents 003157 and 423 represents 000423. You want to know its tenth number. If you know the exact values of k and p, then you can predict the tenth number. However, there are many candidates for k and p: one extreme case is k=5 and p=1, and another is k=0 and p=6. The most probable candidate is the one where both k and p are small. So, our choice is the one with the smallest k+p. If there are two or more such pairs, we pick the one where p is the smallest. With our example, after some tedious computation, we get k=1 and p=2.

Assume that you have n consecutive outcomes of a slot machine, T[1], T[2], …, T[n]. Write a program to compute the values of k and p satisfying the above-mentioned condition.

 

输入

Your program is to read from standard input. The first line contains a positive integer n (1 ≤ n ≤ 1,000,000), representing the length of numbers we have observed up to now in the outcome sequence. The following line contains n numbers. Each of these numbers is between zero and 999,999.

 

输出

Your program is to write to standard output. Print two integers k and p in one line.

 

样例输入

6
612534 3157 423 3157 423 3157

 

样例输出

1 2

题意:

连续删除k 个数, 使得后面的数有循环节 ,且循环节长度为p

使得 k+p  尽可能的小,且当 k+p 一样时,选择p小的.

 

[思路]

  题意 转化成  给你 一串数,   选择后面的一些,求循环节..

求循环节.   KMP 算法里  next数组  就可以  求  :   

循环节为 :  len - next[len];     

循环 次数 为 : if len %( len-next[len]) == 0  then  cot = len / ( len - next[len])

这里用不到 循环次数, 只需要 循环节长度,  

 

只需要把数组逆置一下,然后 枚举  k    求解.

 

[代码]

#include <bits/stdc++.h>
#include <stdio.h>
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define per(i,a,n) for(int i=n;i>=a;i--)

typedef long long ll;
const int maxn = 1e6+10;
const int mod =1e9+7;
const int inf = 0x3f3f3f3f;
using namespace std;

int a[maxn],vis[maxn];
int n;
int net[maxn];
void getfail(int p[],int n) //字符串p自我匹配   
{
    int len = n;
    net[0]=net[1]=0;
    for(int i=1;i<len;i++)
    {
        int j=net[i];
        while(j&&p[i]!=p[j])
            j=net[j];
        if(p[i]==p[j])
            net[i+1]=j+1;//多匹配到了一个字符  
        else
            net[i+1]=0;//该字符配不上   
    }
}

int main(int argc, char const *argv[])
{
	int n;
	scanf("%d",&n);
	rep(i,0,n-1)
	{
		scanf("%d",&a[i]);
	}
	reverse(a,a+n); // 逆置
	getfail(a,n); // 求 next
	int mx = inf;
	int p = 0;
	int k = 0;
	rep(i,1,n) // 枚举 k
	{ 
		int lenp = (n-i+1 - net[n-i+1]); // 循环节..

		if( i+lenp < mx || (i+lenp)== mx && lenp < p )  // 
		{
			mx = i+lenp;
			p = lenp;
			k = i-1;
		}
	}
	printf("%d %d\n",k,p );

	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值