zoukankan      html  css  js  c++  java
  • Gym 100500B

    题目给了四个轮子,每个轮子上有按顺序排列的n个数,要求适当旋转每个轮子,使得四个轮子相同行数相加和相同。

    首先,可以计算出每一行的和应该是多少,记为Sum。然后固定第一个轮子,二重循环枚举2、3轮子,然后O(n)判断1+2+3是否等于Sum-4,这样时间复杂度是O(n^3)。

    那么,只要把判断过程复杂度尽量降低就行了。

    假设每个轮子最大的数是W,那么我们可以把每个轮子看成一个W+1进制数,然后我们把这个数Hash出来,我们轮子每Shift一位,就相当于Hash把最高位减掉并在最低位加上它。然后,计算Hash(1)+HASH(2)+Hash(3)是否等于Hash(Sum...Sum), 其中Sum...Sum代表n个Sum的W+1进制数。这样做到了O(1)的判断。但是Hash可能会有重复,那么,我们用一个multimap来保存每一个Hash值对应的若干个可能的4轮子的位置,然后暴力判断这种状态是否真的可行就行了。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <algorithm>
     4 #include <cstring>
     5 #include <cmath>
     6 #include <map>
     7 #define maxn 2200
     8 #define w 4000001
     9 #define p 1000000007
    10 
    11 using namespace std;
    12 multimap<long long,int> v;
    13 multimap<long long,int>::iterator it;
    14 
    15 int a[5][maxn];
    16 long long hash[5];
    17 long long sum,mx,ss;
    18 int n;
    19 
    20 bool judge(int i,int j,int k)
    21 {
    22     for (int o=0;o<n;o++) 
    23         if (a[1][o]+a[2][(i+o)%n]+a[3][(j+o)%n]+a[4][(k+o)%n]!=sum) return 0;
    24     return 1;
    25 }
    26 
    27 bool solve()
    28 {
    29     for (int i=0;i<n;i++)
    30     {
    31         for (int j=0;j<n;j++)
    32         {
    33             long long h=(hash[1]+hash[2]+hash[3])%p;
    34             for (it=v.lower_bound(h);it!=v.upper_bound(h);it++)
    35             { 
    36                 int k=it->second;
    37                 if (judge(i,j,k)) return 1;
    38             }
    39             hash[3]=(hash[3]*w%p+a[3][j]*(1-mx+p)%p)%p;
    40         }
    41         hash[2]=(hash[2]*w%p+a[2][i]*(1-mx+p)%p)%p;
    42     }
    43     return 0;
    44 }
    45 
    46 int main()
    47 {
    48     int Case;
    49     scanf("%d",&Case);
    50     for (int t=1;t<=Case;t++)
    51     {
    52         sum=0;
    53         scanf("%d",&n);
    54         memset(hash,0,sizeof(hash));
    55         for (int i=1;i<=4;i++)
    56             for (int j=0;j<n;j++)
    57             {
    58                 scanf("%d",&a[i][j]);
    59                 hash[i]=(hash[i]*w%p+a[i][j])%p;
    60                 sum+=a[i][j];
    61             }
    62         sum=sum/n;
    63         mx=1,ss=0;
    64         for (int i=0;i<n;i++) mx=(mx*w)%p,ss=(ss*w%p+sum)%p;
    65         v.clear();
    66         for (int i=0;i<n;i++)
    67         {
    68             v.insert(make_pair((ss-hash[4]+p)%p,i));
    69             hash[4]=(hash[4]*w%p+a[4][i]*(1-mx+p)%p)%p;
    70         }
    71         if (solve()) printf("Case %d: Yes
    ",t);
    72         else printf("Case %d: No
    ",t);
    73     }
    74     return 0;
    75 }
    View Code
  • 相关阅读:
    关于WebBrowser(浏览器)控件的调用
    SQLite3.0 beta & ADO.NET Data Provider for SQLite 0.18发布了!
    特别推荐:纯VB.NET代码直接生成Excel文件(不需要Excel)
    关于ASP.NET中独立页面设置身份认证等问题
    关于实时网站资源监控
    关于SQLite.org网站给黑...
    .NET中调用COM的一些问题
    关于数据库空字段和DEFAULT值等问题
    关于软件保护的矛与盾
    (转贴) 微软面试100题——要想成为盖茨就来试试!
  • 原文地址:https://www.cnblogs.com/zig-zag/p/4499057.html
Copyright © 2011-2022 走看看