Codeforces 1322C C. Instant Noodles(hash+思维)

题目链接:C. Instant Noodles

题意:给定一个二分图的右半部分和对应权值,以及全部边,对于左边部分的任意集合S,都有对应集合N(S)包含所有和集合S中相连的来自右边的点,f(S)代表N(S)中所有点权的和,现让你求所有集合S对应f(S)的最大公因数

题解:我们设集合Xi代表点i连接的左边点组成的集合,那么对于任意i,j满足Xi==Xj时,这两个点要么同时出现在某个集合N(S)中,要么同时不出现,那么我们可以利用hash映射每个右边点对应的Xi,把相同X的点缩点,因为缩点后每个点都是独立的可选或不可选,那么f(s)一定是缩点后点对应权值的自由组合,所以求所以f(s)的gcd时就相当于每个缩点后单独点权的gcd,即gcd(a,a+b+c)==gcd(a,gcd(b,c)) ,即对缩点后的每个点直接求公共gcd即可, 

注意:记得特判X为空集合时

不懂和细节间代码及注释:

#include<iostream>
#include<stack>
#include<list>
#include<set>
#include<vector>
#include<algorithm>
#include<math.h>
#include<numeric>
#include<map>
#include<cstring>
#include<queue>
#include<iomanip>
#include<cmath>
#include<queue>
#include <bitset>
#include<unordered_map>
	#ifndef local
	#define endl '\n'
#endif */
#define mkp make_pair
using namespace std;
using std::bitset;
typedef long long ll;
typedef long double ld;
const int inf=0x3f3f3f3f;
const ll MAXN=2e6+10;
const ll N=1e5+100;
const ll mod=1e9+7;
const ll hash_p1=1610612741;
const ll hash_p2=805306457;
const ll hash_p3=402653189;
//-----------------------------------------------------------------------------------------------------------------*/
// ll head[MAXN],net[MAXN],to[MAXN],edge[MAXN]/*流量*/,cost[MAXN]//费用;
/* 
void add(ll u,ll v,ll w,ll s){
	to[++cnt]=v;net[cnt]=head[u];edge[cnt]=w;cost[cnt]=s;head[u]=cnt;
	to[++cnt]=u;net[cnt]=head[v];edge[cnt]=0;cost[cnt]=-s;head[v]=cnt;
}
struct elemt{
	int p,v;
};
-----------------------------------
求[1,MAXN]组合式和逆元 
ll mi(ll a,ll b){
	ll res=1;
	while(b){
		if(b%2){
			res=res*a%mod;
		}	
		a=a*a%mod;
		b/=2;
	}
	return res;
}
ll fac[MAXN+10],inv[MAXN+10]
ll C(int m,int n){//组合式C(m,n); 
	if(!n){
		return 1;
	}
	return fac[m]*(inv[n]*inv[m-n]%mod)%mod;
}
fac[0]=1;inv[0]=1;
for(ll i=1;i<=MAXN;i++){
	fac[i]=(fac[i-1]*i)%mod;
	inv[i]=mi(fac[i],mod-2);
}
---------------------------------
 unordered_map<int,int>mp;
//优先队列默认小顶堆 , greater<int> --小顶堆  less<int> --大顶堆  
priority_queue<elemt,vector<elemt>,comp>q;
struct comp{
	public:
		bool operator()(elemt v1,elemt v2){
			return v1.v<v2.v;
		}
};
	set<int>::iterator it=st.begin();
*/
// vector<vector<int>>edge; 二维虚拟储存坐标 
//-----------------------------------------------------------------------------------------------------------------*/
  //map<int,bool>mp[N]; 
ll base=1331;
ll h[5*N];
struct elemt{//hsh代表当前右边点连接的左边点组成的集合映射的hash值,c代表当前点上的权值
	ll hsh,c;
};
elemt a[5*N];
void init(int n){
	h[0]=1;
	for(int i=1;i<=n;i++){
		h[i]=h[i-1]*base;
	}
}
ll gcd(ll a,ll b){
	return a%b==0?b:gcd(b,a%b);
}
bool comp(elemt v1,elemt v2){
	return v1.hsh<v2.hsh;
}
int main(){
/*cout<<setiosflags(ios::fixed)<<setprecision(8)<<ans<<endl;//输出ans(float)格式控制为8位小数(不含整数部分)*/
/*cout<<setprecision(8)<<ans<<endl;//输出ans(float)格式控制为8位小数(含整数部分)*/
	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);//同步流
	init(500000);//初始化hash点
	int t;
	cin>>t;
	while(t--){
		int n,m;
		cin>>n>>m;
		for(int i=1;i<=n;i++){//用多少清多少
			a[i].hsh=0;
		}
		for(int i=1;i<=n;i++){
			cin>>a[i].c;
		}
		for(int i=1;i<=m;i++){//确定各点连接的左边点组成的集合
			int u,v;
			cin>>u>>v;
			a[v].hsh+=h[u];
		}
		sort(a+1,a+n+1,comp);//按hsh排序,就能找到对应集合相同的点并缩点
		vector<ll>val;//缩点后对应权值
		for(int i=2;i<=n;i++){
			if(a[i].hsh==a[i-1].hsh){
				a[i].c+=a[i-1].c;
			}
			else if(a[i-1].hsh){//hsh为0说明是空集合,不能算到gcd里面
				val.push_back(a[i-1].c);
			}
		}
		if(a[n].hsh){//hsh为0说明是空集合,不能算到gcd里面
			val.push_back(a[n].c);
		}
		ll ans=val[0];
		for(int i=1;i<val.size();i++){//求gcd
			ans=gcd(ans,val[i]);
		}
		cout<<ans<<endl;
	}
	return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据提供的引用内容,Codeforces Round 511 (Div. 1)是一个比赛的名称。然而,引用内容中没有提供与这个比赛相关的具体信息或问题。因此,我无法回答关于Codeforces Round 511 (Div. 1)的问题。如果您有关于这个比赛的具体问题,请提供更多的信息,我将尽力回答。 #### 引用[.reference_title] - *1* [Codeforces Round 860 (Div. 2)题解](https://blog.csdn.net/qq_60653991/article/details/129802687)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Codeforces Round 867 (Div. 3)(A题到E题)](https://blog.csdn.net/wdgkd/article/details/130370975)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [Codeforces Round 872 (Div. 2)(前三道](https://blog.csdn.net/qq_68286180/article/details/130570952)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值