div1 C
这题的是给了一个无限循环的子数组,问有多少个 (l,s)l代表起点s代表长度的循环串,使得所有的在原串中的每位都小于等于另外这个串(l<=n,1<=s<n)
像这样,我们可以枚举n的因子,类似寻找素数的那种方法去搞,在一个循环中我们就可以知道这个点可以不可以选择了,然后每次都计算一次这个区间,看有多少个符合
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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 ",ans); return 0; }