Clock Pictures(KMP 给了两个指针个数一样时钟,旋转其中一个是否能得到另一个)

 

You have two pictures of an unusual kind of clock. The clock has n hands, each having the same length and no kind of marking whatsoever. Also, the numbers on the clock are so faded that you can’t even tell anymore what direction is up in the picture. So the only thing that you see on the pictures, are n shades of the n hands, and nothing else

You’d like to know if both images might have been taken at exactly the same time of the day, possibly with the camera rotated at different angles.

Task

Given the description of the two images, determine whether it is possible that these two pictures could be showing the same clock displaying the same time.

Input

The first line contains a single integer n (2 ≤ n ≤ 200 000), the number of hands on the clock

Each of the next two lines contains n integers ai (0 ≤ ai < 360 000), representing the angles of the hands of the clock on one of the images, in thousandths of a degree. The first line represents the position of the hands on the first image, whereas the second line corresponds to the second image. The number ai denotes the angle between the recorded position of some hand and the upward direction in the image, measured clockwise. Angles of the same clock are distinct and are not given in any specific order.

Output

Output one line containing one word: possible if the clocks could be showing the same time, impossible otherwise.

题意:给了两个指针数相同的时钟,每个指针都有一个角度(一个圆分成360000份),问这两个钟表可不可能指向的是同一个时间。

思路:其实刚开始做的时候想到哈希,然后被一个取余以及卡常卡到了,后来听大佬说可以用KMP。

KMP做法,因为我们现在有角度,所以我们先对角度进行排序,这样相邻的指针总是在一起的(除首末外),那么此时我们就可以对这些角度作差(a1[], b1[]),这样相邻指针之间的角度差就知道了,如果两个时钟的角度差都一样,那么就可以认定这两个时钟拥有同一个时间。我们再看,由于钟表是圆形的,那么角度差也应该是一个环形,所以要对其中一个角度差求两次了(我用的是a1),注意,首尾相减时,可能为负数,要进行特殊处理。

上面都处理好的话,把b1在a1中跑一遍KMP即可。

代码如下:

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<queue>
#include<stack>
#include<string>
#include<map>
#include<set>
#include<vector>
#include<iostream>
#define inf 0x3f3f3f3f
#define ll long long
#define mod 1e9+7
#define N  200010
using namespace std;
const double pi=acos(-1.0);
int a[N],b[N],a1[N<<1],b1[N],Next[N];
void get_next(int *s,int l)
{
    int i=0,k=-1;
    Next[0]=-1;
    while(i<l)
    {
        if(k<0||s[i]==s[k])
            Next[++i]=++k;
        else k=Next[k];
    }
}
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=0; i<n; i++)
        scanf("%d",&a[i]);
    for(int i=0; i<n; i++)
        scanf("%d",&b[i]);
    sort(a,a+n);
    sort(b,b+n);
    int m=0;
    for(int i=1; i<n; i++)
        a1[m++]=a[i]-a[i-1];
    a1[m++]=(a[0]-a[n-1]+360000)%360000;
    for(int i=1; i<n; i++)
        a1[m++]=a[i]-a[i-1];
    for(int i=1; i<n; i++)
        b1[i-1]=b[i]-b[i-1];
    get_next(b1,n-1);
    int i=0,k=-1,flag=0;
    while(i<m)
    {
        if(k<0||a1[i]==b1[k])
            i++,k++;
        else k=Next[k];
        if(k>=n-1)
        {
            flag=1;
            break;
        }
    }
    if(flag)printf("possible\n");
    else printf("impossible\n");
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值