51NOD 1282 时钟

题目来源:  Codility
基准时间限制:1 秒 空间限制:131072 KB 分值: 40  难度:4级算法题
 收藏
 关注
有N个时钟,每个时钟有M个指针,P个刻度。时钟是圆形的,P个刻度均分整个圆。每个时钟每个指针指向整数刻度,并且每个时钟自身指针指向的数字都不同。你可以任意旋转时钟的表盘,但是你不能转指针。问最后有多少对时钟可以变成相同的状态。

例如:N = 5,M = 2,P = 4,5个时钟的数据如下{1, 2} {2, 4} {4, 3} {2, 3} {1, 3}


经过旋转后。 其中(1, 3), (1, 4), (2, 5) 和 (3, 4)是相同的。


给出所有时钟的数据,求有多少对时钟是相同的。
Input
第1行:3个数N, M, P中间用空格分隔,其中N为时钟的数量,M为表针的数量,P为刻度的数量(1 <= M, N <= 500, 1 <= P <= 10^9, M <= P)。
第2 - N + 1行:每行M个数,对应一个时钟,M个指针的位置。
Output
输出有多少对时钟是相同的。
Input示例
5 2 4
1 2
2 4
4 3
2 3
1 3
Output示例
4
李陶冶  (题目提供者)

STL土法大炼钢一下就好了...一个指针序列 可以转化为 一个长度为M的,相邻2个指针间差值的序列

问题就是求这样的序列相同的数量

循环数组,找出字典序最小的差值序列,放map里即可

#include <bits/stdc++.h>

#define ll long long
#define pii pair<int,int>
#define MEM(a,x) memset(a,x,sizeof(a))

using namespace std;

const int inf=1e9+7;

const int N = 500+5;

int a[N];
map<deque<int>,int>mp;

void add(int*a,int m,int p){
    sort(a,a+m);
    int a0=a[0];
    for(int i=0;i<m-1;++i){
        a[i]=a[i+1]-a[i];
    }
    a[m-1]=p+a0-a[m-1];
    deque<int>tmp,ans;
    tmp.assign(a,a+m);
    ans.assign(a,a+m);
    for(int i=0;i<m;++i){
        tmp.push_back(a[i]);
        tmp.pop_front();
        ans=min(ans,tmp);
    }
    mp[ans]+=1;;
}

int slove(){
    int ans=0;
    for(auto&it:mp){
        int x=it.second;
        ans+=(x-1)*x/2;
    }
    return ans;
}

int main()
{
    //freopen("/home/lu/code/r.txt","r",stdin);
    int n,m,p;
    while(~scanf("%d%d%d",&n,&m,&p)){
        mp.clear();
        for(int i=0;i<n;++i){
            for(int j=0;j<m;++j){
                scanf("%d",&a[j]);
            }
            add(a,m,p);
        }
        printf("%d\n",slove());
    }
    return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值