Codeforces Round #323

div1 C

这题的是给了一个无限循环的子数组,问有多少个 (l,s)l代表起点s代表长度的循环串,使得所有的在原串中的每位都小于等于另外这个串(l<=n,1<=s<n)

像这样,我们可以枚举n的因子,类似寻找素数的那种方法去搞,在一个循环中我们就可以知道这个点可以不可以选择了,然后每次都计算一次这个区间,看有多少个符合

#include <iostream>
#include <cstdio>
#include <string.h>
#include <vector>
#include <algorithm>
using namespace std;
const int maxn=200005;
typedef long long LL;
int phi[maxn],G[maxn];
int gcd(int a,int b){
   return b?gcd(b,a%b):a;
}
void phi_table(int n,int g)
{
    phi[0]=0;
    for(int i=1; i<n; i++)if(G[i]!=g)phi[i]=phi[i-1];
    else phi[i]=phi[i-1]+1;
}
int a[maxn];
bool use[maxn],ismax[maxn];
int main()
{
    int n;
    LL ans=0;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)G[i]=gcd(i,n);
    for(int i=0;i<n; i++)
        scanf("%d",&a[i]);
    for(int i=1; i<n; i++)
        {
            if(n%i!=0)continue;
            phi_table(n,i);
            memset(use,false,sizeof(use));
            memset(ismax,false,sizeof(ismax));
            for(int j=0; j<i; j++)
                {
                    int ma=-1;
                    for(int k=j; k<n; k+=i)ma=max(a[k],ma);
                    for(int k=j; k<n; k+=i)
                        if(a[k]==ma)ismax[k]=true;
                }
            int r=0;
            for(int j=0; j<n; j++)
            {
                if(r<j)r=j;
                while(true){
                    if(r>=n && (r%n)==j)break;
                    if(ismax[r%n]==false)break;
                    else r++;
                }
                int d=min(n-1,r-j);
                ans+= phi[d];
            }

        }
        printf("%I64d\n",ans);
    return 0;
}
View Code

 

ddd

 

posted @ 2015-10-05 12:26  来自大山深处的菜鸟  阅读(182)  评论(0编辑  收藏  举报