zoukankan      html  css  js  c++  java
  • J. Periodic Ruler题解

    J. Periodic Ruler

    随便拉了个四星的比赛,然后就稀碎了....
    被这个题给干烂了...吐了...
    这个题一直很不理解题意,让我再简述下题意吧。
    在一个坐标轴上,每个点都有一个颜色。颜色的编号最多就是1到100.其次还有一个最小周期T,每个颜色都满足这个周期,即\(c_i=c_{i+T}\).现给定你若干个点的坐标和他们的颜色。问所有不满足的T的和。没有颜色的坐标你可以随便染任何颜色。
    首先考虑周期T的影响,就想到同余,也就是说在0-T-1的余数中,每个余数只能被一种颜色占领。先考虑已有的点中,若两个点的颜色不同,则说明周期T中,他们不能处于同一个余数,这个很容易推到T是\(|x_i-x_j|\)的因子的时候,他们处于同一个余数。所以我们可以\(O(n^2)\)枚举所有的点对,再\(\sqrt{max(xi)}\)枚举其因子即可。剩下的情况就是所有颜色相同的点在同一个余数中,颜色不同的点不在一个余数中。但发现这个题的第二个样例都过不去,因为可能你的周期T不是最小的正周期。考虑什么时候你的周期T不是最小的正周期,考虑若你的周期T的所有余数系没有被填满的话,那么剩下的没有颜色的余数系,我们可以染任意的颜色,考虑这种情况下,能不能被更小的T所代替。考虑什么情况下一个T能被另一个更小的t所代替,必须满足这两个T,t形成的序列是相同。那么也就必须保证,T的余数系中能够被t的余数系填满并延伸得到。这里说复杂了,其实就是t必须是T的因子。且,T的余数系按照t分成若干段,必须是相同的。这样的话,才能被小t代替。但我们考虑刚才的情况,我们有的颜色没有涂满,我们完全可以让这个点和之前对应的点不同,构造一个使得T合法的情况。那么剩下的情况就是一个T的余数系被填满了,那我们就枚举一下它的因子,看当前T能否被它的因子代替即可。这里注意到,因为给到的点只有50个,所以能被代替的T最大是50,因为我们需要满足他的余数系被填满。那这个复杂度就为\(O(n^3)\).

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int N=110;
    int x[N],c[N],n,vis[N];
    set<int>s;
    
    inline bool check1(int T)
    {
        for(int i=0;i<T;++i) if(!vis[i]) return false;
        return true;
    }
    
    inline bool check2(int T,int t)
    {
        for(int i=0;i<T;++i)
        {
            if(vis[i]!=vis[i%t]) return false;
        }
        return true;
    }
    
    int main()
    {
    //    freopen("1.in","r",stdin);
        scanf("%d",&n);
        for(int i=1;i<=n;++i) scanf("%d%d",&x[i],&c[i]);
        for(int i=1;i<=n;++i)//处理颜色不同的点造成的不合法的情况。 
            for(int j=i+1;j<=n;++j)
            {
                if(c[i]!=c[j])
                {
                    int sx=abs(x[i]-x[j]);
                    for(int k=1;k<=sqrt(sx);++k)
                    {
                        if(sx%k==0)  
                        {
                            s.insert(k);
                            s.insert(sx/k);   
                        }
                    }
                }
            }
        for(int T=1;T<=50;++T)//枚举所有可能被替代的T。 
        {
            memset(vis,0,sizeof(vis));
            for(int i=1;i<=n;++i)
            {
                int d=((x[i]%T)+T)%T;
                vis[d]=c[i];
            }
            if(!check1(T)) continue;//没被填满一定不能被替代。
            for(int j=1;j<T;++j)//判断T能否被j替代。 
            {
                if(T%j==0&&check2(T,j)) 
                {
                    s.insert(T);
                    break;
                } 
            } 
        }    
        ll ans=0,cnt=0;
        for(auto z:s)  ans+=z,cnt++;
        printf("%lld %lld\n",cnt,ans);
        return 0;
    } 
    
  • 相关阅读:
    EasyTransaction主要源码分析
    编程哲理小故事:Tina的运动会方阵
    多维扩展点的思考与设计——解决渠道、产品增加引发的腐化问题
    分布式事务框架Seata及EasyTransaction架构的比对思考
    设计,架构,框架之间是什么关系?
    你知道如何画好一幅架构图么?
    学会分享痛苦
    建立你自己的博客
    使用正确的工具软件
    掌握主动权
  • 原文地址:https://www.cnblogs.com/gcfer/p/15520613.html
Copyright © 2011-2022 走看看