• 【CodeForces】582 C. Superior Periodic Subarrays


    【题目】C. Superior Periodic Subarrays

    【题意】给定循环节长度为n的无限循环数列,定义(l,s)表示起点为l的长度为s的子串,(l,s)合法要求将子串从该起点开始以s为循环节长度无限循环中每个数字都>=数列中对应位置的数字,求合法(l,s)的数量。0<=l<n,1<=s<=n,n<=2*10^5,1<=ai<=10^6。

    【算法】数论,计数问题

    【题解】先不考虑起点,对于选定的s,子串中的数字必须≥所有间隔为g=gcd(s,n)的数字(核心思想)

    例如在1 2 3 4 5 6,g=2时,1 3 5为一组,2 4 6为一组,子串中如果包含某一组的一个,那个就必须≥整组的数字。

    枚举g,对于数列中g个[数字间隔为g的序列],显然每个序列中只有最大的数字才有可能被选择为子串,那么处理后我们得到了01数列。

    对于01数列,我们要用连续的1凑出长度s满足gcd(s,n)=g,先使用双指针统计出几段连续的1,对于每一段连续的1枚举长度贡献答案。

    复杂度O(d(n)*n),其中d(n)为n的因子个数。

    以上为CF官方题解,在处理01序列的时候可以采用一种较简单的写法:

    枚举g,预处理c[x]表示长度i=1~x中满足g=gcd(i,n)的 i 的个数。

    处理出01序列,然后将链复制一遍,倒着计算出b[i]表示从i出发最长的连续1个数。

    最后枚举起点l,每个点贡献答案c[b[i]]。

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int maxn=200010;
    int n,a[maxn],b[maxn<<1],c[maxn],mx[maxn],gc[maxn];
    int gcd(int a,int b){return !b?a:gcd(b,a%b);}
    //learn from LIBERATOR
    int main(){
        scanf("%d",&n);
        for(int i=0;i<n;i++)scanf("%d",&a[i]);
        for(int i=1;i<n;i++)gc[i]=gcd(i,n);
        long long ans=0;
        for(int g=1;g<n;g++)if(n%g==0){
            for(int i=1;i<=n;i++)c[i]=c[i-1]+(gc[i]==g);
            for(int i=0;i<g;i++)mx[i]=a[i];
            for(int i=g;i<n;i++)mx[i%g]=max(mx[i%g],a[i]);
            for(int i=0;i<n;i++)b[i]=b[i+n]=(mx[i%g]==a[i]);
            for(int i=n+n-2;i>=0;i--)if(b[i])b[i]+=b[i+1];
            for(int i=0;i<n;i++)ans+=c[min(n-1,b[i])];
        }
        printf("%lld",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    Python字符串的切片
    Python字符串的劈分
    Python函数的参数
    接口幂等性
    Kafka 中的设计思想
    Stream特性
    API接口的安全设计验证:ticket,签名,时间戳
    linux命令
    Java注解和反射
    su 和 sudo
  • 原文地址:https://www.cnblogs.com/onioncyc/p/7944055.html
Copyright © 2020-2023  润新知