朋友

【簡要題意】
每個人手上寫着4個互不相同的數。如果兩個人至少有一個數字相同,則他們是一對朋友。現在這n個人按序號從左到右排成了一排,每個人都想知道在他左邊有多少個人是他的朋友。
n<=1e5,所有數字均是不大於50的非負整數。

【分析】
發現數字的範圍很小,所以我們可以考慮枚舉數字求朋友數,但發現存在重複統計的情況。再次考慮這種算法,相當於求前面的數字關於這四個數的全集。所以用容斥原理加加減減即可。手(nao)抽用了map+hash存,費了一些勁才卡過時限。突然發現這種解法好像還可以用於解決數字更大的情況。

【code】

#pragma GCC optimize(2)
#include<map>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=1e5+100;
const int base=67;
int n,cnt;
map<int,int>mp;
int a[maxn][5];
int p[5];
inline void read(int &x){
	x=0;int fl=1;char tmp=getchar();
	while(tmp<'0'||tmp>'9'){if(tmp=='-')fl=-fl;tmp=getchar();}
	while(tmp>='0'&&tmp<='9') x=(x<<1)+(x<<3)+tmp-'0',tmp=getchar();
	x=x*fl;
}
inline int hash(int len){
	register int ret=0;
	for(register int i=len;i>=1;i--)
		ret=ret*base+p[i]+1;
	return ret;
}
int pos,lmt;
void dfs(int u,int dep){
	if(dep>lmt){
		register int h=hash(lmt);
		if(lmt&1)cnt+=mp[h];
		else cnt-=mp[h];
		mp[h]++;
		return ;
	}
	for(register int i=u;i<=4;i++){
		p[dep]=a[pos][i];
		dfs(i+1,dep+1);
	}
}
void write(int x){
	if(x>9) write(x/10);
	putchar(x%9+'0');
}
int main(){
	freopen("friend.in","r",stdin);
	freopen("friend.out","w",stdout);
	cin>>n;
	for(register int i=1;i<=n;i++){
		for(register int j=1;j<=4;j++)
			read(a[i][j]);
		sort(a[i]+1,a[i]+5);
	}
	for(register int i=1;i<=n;i++){
		cnt=0,pos=i;
		for(register int j=1;j<=4;j++)lmt=j,dfs(1,1);
		printf("%d\n",cnt);
	}
	return 0;
}

再放一下同學用數組存的解法(大霧):

#include<bits/stdc++.h>
#define a x[1]
#define b x[2]
#define c x[3]
#define d x[4]
using namespace std;
int read(){
	int u=0,f=1;char cc=getchar();
	while(cc<'0'||cc>'9') f=(cc=='-'?-1:1),cc=getchar();
	while(cc>='0'&&cc<='9') u=(u<<1)+(u<<3)+cc-'0',cc=getchar();
	return u*f;
}
int n,x[5];
int on[51],tw[51][51],th[51][51][51],fo[51][51][51][51];

int main(){
	freopen("friend.in","r",stdin);
	freopen("friend.out","w",stdout);
	n=read();
	for(int i=1;i<=n;i++){
		a=read(),b=read(),c=read(),d=read();
		sort(x+1,x+5);
		printf("%d\n",on[a]+on[b]+on[c]+on[d]-tw[a][b]-tw[a][c]-tw[a][d]-tw[b][c]-tw[b][d]-tw[c][d]+th[a][b][c]+th[a][b][d]+th[a][c][d]+th[b][c][d]-fo[a][b][c][d]);
		on[a]++,on[b]++,on[c]++,on[d]++;
		tw[a][b]++,tw[a][c]++,tw[a][d]++,tw[b][c]++,tw[b][d]++,tw[c][d]++;
		th[a][b][c]++,th[a][b][d]++,th[a][c][d]++,th[b][c][d]++;
		fo[a][b][c][d]++;
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章