题目大意:给定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));
}
}