CodeForces - 582C Superior Periodic Subarrays(数论&计数)
题目大意
给出一段纯循环序列a,循环节的长度为n.求有多少对数对(l,s)总是满足以s为循环节,循环节中数字为 a l , a l + 1 . . a l + s − 1 a_l,a_{l+1}..a_{l+s-1} al,al+1..al+s−1的序列设为b使得总是有 b i − l + 1 ≥ a i b_{i-l+1}\ge a_i bi−l+1≥ai其中 i > = l i>=l i>=l
解题思路
题意可以简单地用数学式子来表示
a
k
≥
a
(
q
∗
s
+
k
)
%
n
a_k\ge a_{(q*s+k)\%n}
ak≥a(q∗s+k)%n
其中q为任意大于等于0的常数,
k
∈
[
l
,
l
+
s
−
1
]
k\in[l,l+s-1]
k∈[l,l+s−1]
其中 ( q ∗ s + k ) % n (q*s+k)\%n (q∗s+k)%n可以化为 q ∗ s + n ∗ b + k q*s+n*b+k q∗s+n∗b+k由整除理论得知 q ∗ s + n ∗ b = l ∗ g c d ( n , s ) q*s+n*b=l*gcd(n,s) q∗s+n∗b=l∗gcd(n,s)其中l为任意整数由此得出所选出的序列必须保证序列中的每个数都是间隔 g c d ( s , n ) gcd(s,n) gcd(s,n)的所有数段中最大的数
据此将原字符串化为01串.根据不同长度的01串算出贡献最终得到答案
AC代码
#include<bits/stdc++.h>
using namespace std;
const int size=2e5+5;
int c[size];
int b[2*size];
int maxn[size];
int arr[size];
int gcds[size];
int main()
{
int n;
cin>>n;
for(int i=0;i<n;i++) cin>>arr[i];
for(int i=1;i<n;i++) gcds[i]=__gcd(i,n);
long long ans=0;
for(int i=1;i<n;i++)
{
if(n%i) continue;
for(int j=1;j<=n;j++) c[j]=c[j-1]+(gcds[j]==i);
for(int j=0;j<i;j++) maxn[j]=0;
for(int j=0;j<n;j++) maxn[j%i]=max(maxn[j%i],arr[j]);
for(int j=0;j<n;j++) b[j+n]=b[j]=(maxn[j%i]==arr[j]);
for(int j=2*n-2;j>=0;j--) if(b[j]) b[j]=b[j]+b[j+1];
for(int j=0;j<n;j++) ans+=c[min(n-1,b[j])];
}
cout<<ans<<endl;
}