[HNOI2010]物品调度 **题
为毛出题人不好好出数据啊 ...
这个
首先它这个
因为每个点都有一个出边而且固定步长为
所以
所以一个暴力做法就是从小到大枚举
因为在同一个环内的步长固定为
然而只优化找
大体思路就是这样,但是还有一点小细节。假设
#include<bits/stdc++.h>
using std::min;
using std::max;
using std::swap;
using std::vector;
typedef double db;
typedef long long ll;
#define pb(A) push_back(A)
#define pii std::pair<int,int>
#define all(A) A.begin(),A.end()
#define mp(A,B) std::make_pair(A,B)
const int N=1e5+5;
int pos[N],vis[N];
int c[N],belong[N];
int n,q,p,m,d,s,tot;
struct bcj{
int father[N];
void init(){for(int i=0;i<n;i++) father[i]=i;}
int find(int x){return father[x]==x?x:father[x]=find(father[x]);}
}A,B;
int getint(){
int X=0,w=0;char ch=getchar();
while(!isdigit(ch))w|=ch=='-',ch=getchar();
while( isdigit(ch))X=X*10+ch-48,ch=getchar();
if(w) return -X;return X;
}
void rem(int x){
int r1=A.find(x),r2=A.find((r1+d)%n);
if(r1!=r2) A.father[r1]=r2;
else{
r1=B.find(belong[x]),r2=B.find((r1+1)%tot);
B.father[r1]=r2;
}
}
int calc(int x,int y){
return (x-y+tot)%tot;
}
signed main(){
int T=getint();
while(T--){
n=getint(),s=getint(),q=getint(),p=getint(),m=getint(),d=getint()%n;
A.init(),B.init();tot=0;
for(int i=1;i<n;i++) c[i]=(1ll*c[i-1]*q+p)%m;
memset(belong,-1,sizeof belong);
for(int i=0;i<n;i++){
if(belong[i]==-1){
for(int j=i;belong[j]<0;j=(j+d)%n)
belong[j]=tot;
tot++;
}
}
rem(s);pos[0]=s;
for(int i=1;i<n;i++){
c[i]%=n;
int pp=B.find(belong[c[i]]);
int qq=A.find((c[i]+calc(pp,belong[c[i]]))%n);
pos[i]=qq;rem(qq);
}
int ans=0;memset(vis,0,sizeof vis);
for(int i=0;i<n;i++){
if(!vis[i]){
vis[i]=1;int now=i;
int cnt=1,flag=now==s;
while(!vis[pos[now]]){
now=pos[now];vis[now]=1;
cnt++;if(now==s) flag=1;
}
if(flag) ans+=cnt-1;
else if(cnt>1) ans+=cnt+1;
}
} printf("%d\n",ans);
} return 0;
}