【题解】CF722F Cyclic Cipher

题目大意:给定n个数列,第 i 个数列包含ki个不超过m的正整数,同一数列里的数互不相同。每一秒将n个数列中的数左移一个位置,每个数列第一个数则移到该数列最后,并在一张纸上记下每个数列的第一个数。10^100秒过后,对于所有的1<=x<=m,求x在纸上出现的最长的连续的一段长度,该段必须是同一秒中记下的数。
数据范围:1 ≤ n, m ≤ 100 000,1 ≤ ki ≤ 40,∑ki<=200 000

solution:
对于每个 i, 相当于在子区间统计答案,考虑双指针。注意到一组同余方程如果有解,那么对于其中任意两个一定满足 a1+k1m1=a2+k2m2 有解,即 gcd(m1,m2)|a2-a1 。又因为 m_i<=40 ,所以暴力判断每种 m_i 不会超过 40 。因为如果有两个相同的模数的话,一定满足 a_i=a_j 。每次新加入一个模数判断之前是否出现过。小优化:对于 f[t2[i]]==1 的情况将模数 1~40 判断,否则说明之前判断过,直接跳过。时间复杂度 O(40nlog40) 。

#include<cstdio> #include<algorithm> #include<cstring> #define ll long long #define PII pair<int,int> #define rd(x) scanf("%lld",&(x)) using namespace std; const int mx=1e5+5; int n,Maxa,c[45],f[45]; int t1[mx],t2[mx],t3[mx],cnt; ll a[mx],m[mx]; vector<PII> vec[mx]; //双指针 yyds ll gcd(ll x,ll y) { return y==0?x:gcd(y,x%y); } ll lcm(ll x,ll y) { if(x==0||y==0) return x^y; return x/gcd(x,y)*y; } ll fmul(ll x,ll y,ll z) { x%=z,y%=z; if(y<0) x=-x,y=-y; ll sum(0); for(;y;y>>=1) { if(y&1) sum=(sum+x)%z; x=(x+x)%z; } return sum; } ll fpow(ll x,ll y,ll z) { x%=z; ll mul(1); for(;y;y>>=1) { if(y&1) mul=mul*x%z; x=x*x%z; } return mul; } ll inv(ll x,ll y) { if(y==1) return 0; return fpow(x,y-2,y); } void exgcd(ll &x,ll &y,ll a,ll b,ll &d) { if(b==0) { x=1,y=0,d=a; } else { exgcd(y,x,b,a%b,d); y-=x*(a/b); } } bool excrt() { for(int i=1;i<=n;i++) { if(a[i]>=m[i]) return 1; } for(int i=2;i<=n;i++) { ll tmp=((a[i]-a[1])%m[i]+m[i])%m[i]; ll k1,k2,d; exgcd(k1,k2,m[1],m[i],d); if(tmp%d) return 1; k1=(k1%(m[i]/d)*(tmp/d)%(m[i]/d)+(m[i]/d))%(m[i]/d); ll M=m[1]/d*m[i]; a[1]=(a[1]+m[1]*k1%M)%M; m[1]=M; } return 0; } ll solve(int id) { cnt=0; for(auto y:vec[id]) { t1[++cnt]=y.first,t2[cnt]=m[y.first],t3[cnt]=y.second; } int j=1,res=0; for(int i=1;i<=cnt;i++) { if(t1[i]!=t1[i-1]+1) { for(;j<i;f[t2[j]]--,j++); } if(f[t2[i]]&&c[t2[i]]!=t3[i]) { for(;j<i&&f[t2[i]];f[t2[j]]--,j++); } f[t2[i]]++,c[t2[i]]=t3[i]; if(f[t2[i]]==1) { for(int k=1;k<=40;k++) { if(f[k]&&(t3[i]-c[k])%gcd(t2[i],k)) { for(;j<i&&f[k];f[t2[j]]--,j++); } } } res=max(res,i-j+1); } for(;j<=cnt;f[t2[j]]--,j++); return res; } int main() { scanf("%d%d",&n,&Maxa); for(int i=1;i<=n;i++) { scanf("%lld",&m[i]); for(int j=0;j<m[i];j++) { int x; scanf("%d",&x); vec[x].push_back(make_pair(i,j)); } } for(int i=1;i<=Maxa;i++) { printf("%lld\n",solve(i)); } }

__EOF__

本文作者仰望星空的蚂蚁
本文链接https://www.cnblogs.com/cqbzly/p/17530267.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   仰望星空的蚂蚁  阅读(6)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
点击右上角即可分享
微信分享提示