题目描述:
大皮出行,妹子成群,似乎这种事早已经司空见惯了。 大皮最终还是厌倦了这样的⽣活,懂得了节制,他希望每次恰好只有三个妹子陪他。
大皮有 $n$个妹子,编号为$0$到$n-1$ ,大皮需要次从$n$个中选出三个来愉悦身心。
那么问题来了,有许多妹子为了得到大皮的欢心,产生了冲突,这样的冲突一共有$m$组,为了让自己的出行能清净些,大皮不希望选出的三个妹子,有任何一对存在冲突。
对于每一次选择的三个妹子$i,j,k(i<j<k)$,大皮可以得到的愉悦值为
$A imes i+B imes j+C imes k$
大皮希望你帮他求出所有方案可以得到的愉悦值之和,由于答案太大,请输出答案$mod 2^{64}$
算法标签:三元环计数,容斥
思路:
对于满足的方案容斥一下。
所有方案-有一条边的+有两条边的-有三条边的
以下代码:
#include<bits/stdc++.h> #define il inline #define ull unsigned long long #define _(d) while(d(isdigit(ch=getchar()))) using namespace std; const int N=2e5+5; bool vis[N]; ull A,B,C,ans; int n,m,q[4],in[N]; struct node{ int l,r; }t[N]; vector<int> v[N]; il int read(){ int x,f=1;char ch; _(!)ch=='-'?f=-1:f;x=ch^48; _()x=(x<<1)+(x<<3)+(ch^48); return f*x; } int main() { n=read();m=read(); scanf("%llu%llu%llu",&A,&B,&C); for(int i=1;i<=n;i++){ if(i<n-1)ans+=A*(ull)(1ll*(n-i)*(n-i-1)/2)*(i-1); if(i!=1&&i!=n)ans+=B*(ull)(1ll*(i-1)*(n-i))*(i-1); if(i>2)ans+=C*(ull)(1ll*(i-1)*(i-2)/2)*(i-1); } for(int i=1;i<=m;i++){ int x=read()+1,y=read()+1; in[x]++;in[y]++; t[i]=(node){x,y}; if(x>y)swap(x,y); ans-=(ull)(B*(x-1)+C*(y-1))*(ull)(x-1)+A*(ull)(1ll*(x-1)*(x-2)/2ll); ans-=(ull)(A*(x-1)+C*(y-1))*(ull)(y-x-1)+B*(ull)(1ll*(y-x-1)*(x+y-2)/2ll); ans-=(ull)(A*(x-1)+B*(y-1))*(ull)(n-y)+C*(ull)(1ll*(n-y)*(y-1+n)/2ll); v[x].push_back(y);v[y].push_back(x); } for(int i=1;i<=n;i++)sort(v[i].begin(),v[i].end()); for(int x=1;x<=n;x++){ int sz=v[x].size()-1; int num1=0,num2=0; for(int i=0;i<=sz;i++){ int to=v[x][i]; if(to<x){ num1++; ans+=A*(to-1)*(sz-i)+B*(to-1)*i; } else{ num2++; ans+=B*(to-1)*(sz-i)+C*(to-1)*i; } } ans+=(ull)(x-1)*(A*(1ll*num2*(num2-1)/2)+B*(1ll*num1*num2)+C*(1ll*num1*(num1-1)/2)); } for(int i=1;i<=n;i++)v[i].clear(); for(int i=1;i<=m;i++){ int x=t[i].l,y=t[i].r; if(in[x]<in[y]||(in[x]==in[y]&&x>y))swap(x,y); v[x].push_back(y); } for(int x=1;x<=n;x++){ for(int i=0;i<v[x].size();i++)vis[v[x][i]]=1; for(int i=0;i<v[x].size();i++){ int to=v[x][i]; for(int j=0;j<v[to].size();j++){ if(vis[v[to][j]]){ q[1]=x-1;q[2]=to-1;q[3]=v[to][j]-1; sort(q+1,q+4); ans-=A*q[1]+B*q[2]+C*q[3]; } } } for(int i=0;i<v[x].size();i++)vis[v[x][i]]=0; } printf("%llu ",ans); return 0; }