BZOJ 1998: [Hnoi2010]Fsk物品调度

很作死地写了个高端(SB)的并查集

首先只要求出所有的posi,剩下的很容易用置换群的理论得出答案

然后看posi的求法

对于固定的a,d

a+b*d(modn)

通过b不断地累加会构成环

于是查找的时候只要找环上xi最小的点。

但是有的时候会把一个环用完

于是我们把环上的每个点都连到相应的下一个环上

然后我很脑残地写了个并查集,维护环与环之间的路径和环内的路径

每次查找的时候先通过环间路径找到环,即yi得值

然后通过环内找到xi

最后更新

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=100000+5;
typedef long long ll;
int pa[N],d,n,circle_number[N];
int find1(int x){
	return pa[x]==x?x:pa[x]=find1(pa[x]);
}
int find2(int x){
	if(d==0||circle_number[x]==circle_number[pa[x]])return x;
	return pa[x]=find2(pa[x]);
}
void merge(int x,int y){
	x=find1(x);y=find1(y);
	if(x!=y)pa[x]=y;
}
bool use[N];
void work(int c){
	use[c]=1;
	if(find1((c+d)%n)==c){
		int r=c;
		do{
			pa[r]=(r+1)%n;
			r=(r+d)%n;
		}while(r!=c);
	}else merge(c,(c+d)%n);
}
int query(int c){
	c=find2(c);
	c=find1(c);
	int ans=c;
	work(c);
	return ans;
}
int pos[N];
bool vis[N],flag;
int dfs(int i){
	if(vis[i])return 0;
	vis[i]=1;if(!i)flag=0;
	return dfs(pos[i])+1;
}
void pre(){
	memset(vis,0,sizeof(vis));
	int tot=0;
	for(int i=0;i<n;i++)
	if(!vis[i]){
		int j=i;
		tot++;
		do{
			vis[j]=1;
			circle_number[j]=tot;
			j=(j+d)%n;
		}while(j!=i);
	}
}
int main(){
	//freopen("a.in","r",stdin);
	//freopen("a.out","w",stdout);
	int T;scanf("%d",&T);
	while(T--){
		ll a,b,m,t;
		int s;
		scanf("%d%d%lld%lld%lld%lld",&n,&s,&a,&b,&m,&t);
		d=t%n;
		memset(use,0,sizeof(use));
		pre();
		for(int i=0;i<n;i++)pa[i]=i;
		work(s);
		ll c=0;
		int ans=0;
		for(int i=1;i<n;i++){
			c=(c*a+b)%m;
			pos[i]=query(c%n);
		}
		pos[0]=s;
		memset(vis,0,sizeof(vis));
		for(int i=0;i<n;i++)
		if(!vis[i]){
			flag=1;
			int l=dfs(i);
			if(l==1)continue;
			ans+=l+(flag?1:-1);
		}
		printf("%d\n",ans);
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值