CodeForces - 582C Superior Periodic Subarrays(数论&计数)

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+s1的序列设为b使得总是有 b i − l + 1 ≥ a i b_{i-l+1}\ge a_i bil+1ai其中 i > = l i>=l i>=l

解题思路

题意可以简单地用数学式子来表示
a k ≥ a ( q ∗ s + k ) % n a_k\ge a_{(q*s+k)\%n} aka(qs+k)%n
其中q为任意大于等于0的常数, k ∈ [ l , l + s − 1 ] k\in[l,l+s-1] k[l,l+s1]

其中 ( q ∗ s + k ) % n (q*s+k)\%n (qs+k)%n可以化为 q ∗ s + n ∗ b + k q*s+n*b+k qs+nb+k由整除理论得知 q ∗ s + n ∗ b = l ∗ g c d ( n , s ) q*s+n*b=l*gcd(n,s) qs+nb=lgcd(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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值