CodeForces - 722F Cyclic Cipher(数论)

CodeForces - 722F Cyclic Cipher(数论)

题目大意

有n个循环无穷序列,第i个序列 a i a_i ai的循环周期为 k i k_i ki,每个序列的第一项 a i , 1 a_{i,1} ai,1到第k项 a i , k i a_{i,k_i} ai,ki为给定的数字.对于每种可能的元素取值,找到一个小标j,找到 j j j使得 j ≤ 1 0 100 j\le10^{100} j10100且序列 a 1 , j , a 2 , j , . . . a n , j {a_{1,j},a_{2,j},...a_{n,j}} a1,j,a2,j,...an,j中有着最长连续的v,问对于每个v输出最长长度

解题思路

首先明确一个问题,两个序列中的两个相同的数字何时会有相同的位置?

首先我们假设有两个序列 a i , a i + 1 a_i,a_{i+1} ai,ai+1都有某个数v,其在 a i a_i ai中第一次出现在 x i x_i xi位,在 a i + 1 a_{i+1} ai+1中第一次出现在 x i + 1 x_{i+1} xi+1位,再假设 a i a_i ai的周期为 T i T_i Ti a i + 1 a_{i+1} ai+1的周期为 T i + 1 T_{i+1} Ti+1则当方程
x i + k i ∗ T i = x i + 1 + k i + 1 ∗ T i + 1 x_i+k_i*T_i=x_{i+1}+k_{i+1}*T_{i+1} xi+kiTi=xi+1+ki+1Ti+1
有解时则可以在同一位出现,也即 ( x i − x i + 1 ) % g c d ( T i , T i + 1 ) = = 0 (x_i-x_{i+1})\%gcd(T_i,T_{i+1})==0 (xixi+1)%gcd(Ti,Ti+1)==0时可以在相同的位置出现

因此有着连续的一段V的序列需要保证这段之间两两都满足上面这个式子.但是直接暴力比较的话时间复杂度则会过大.这时可以发现所有 T ∈ [ 1 , 40 ] T\in[1,40] T[1,40]因此只需要对当前的T对所有的T进行检测即可.且当两条序列有相同的T时,必须其x也相同才可以保证出现在相同的位置,因此一个周期唯一对应一个x,为此维护出所有周期的种类的x,与连续的x的数量即可.通过左右指针对所有的序列进行操作当右指针继续前进会与已经选择的区段产生冲突之后停止右指针的更新,反将左指针进行右移,并使相应的周期所对应的数的数量-1,再进行下一轮的右指针右移

AC代码

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
const int size=1e5+5;
int n[41],cnt[41];
int T[size];
vector<int> a[size];
map<int,vector<pair<int,int>>> b;
bool check(int t,int x)
{
	for(int i=1;i<=40;i++)
		if(cnt[i]&&(n[i]-x)%__gcd(i,t)) return false;
	n[t]=x;cnt[t]++;
	return true;
}
int main()
{
	int  n,m;
	cin>>n>>m;
	int x;
	for(int i=1;i<=n;i++)
	{
		cin>>T[i];
		for(int j=1;j<=T[i];j++)
		{
			cin>>x;
			a[i].push_back(x);
			b[x].push_back(pii(i,j));
		}
	}
	int l,r;
	int ans;
	for(int i=1;i<=m;i++)
	{
		ans=0;
		memset(cnt,0,sizeof(cnt));
		for(l=0,r=0;l<b[i].size();l++)
		{
			for(;r<b[i].size()&&b[i][r].first-b[i][l].first==r-l;r++)
			if(!check(T[b[i][r].first],b[i][r].second)) break;
			ans=max(ans,r-l);
			cnt[T[b[i][l].first]]--;
		}
		cout<<ans<<endl;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值