CSUST 4007-你真的會圖論嗎?(思維-三元環)
題目連結:http://acm.csust.edu.cn/problem/4007
部落格園食用連結:https://blog.csdn.net/qq_43906000/article/details/107813983
Description
給你一張完全無向圖,每條邊有兩種顏色(黑色或者白色),你需要求出有多少個三元環,路徑上邊的顏色相同給你一張完全無向圖,每條邊有兩種顏色(黑色或者白色),你需要求出有多少個三元環,路徑上邊的顏色相同
Input
第一行一個正整數\(n\),表示這張完全圖的點數.\((1 \leq n \leq 5e3)\)
第二行五個整數,\(A,B,C,P,D,1 \leq A,B,C,P,D \leq 10^9\)
,且\(D \leq P\),然後我們規定,對於邊\(i,j(i \lt j)\),如果\((A(i+j)^2 + B(i-j)^2 +C) \mod P>D\),則該邊為黑色,否則為白色.
Output
輸出一個數表示結果
Sample Input 1
6
2 3 4 11 5
Sample Output 1
6
正所謂正難則反,對於直接選出同色的三元環可能會不知道怎麼入手,那麼我們考慮將所有的三元環減去不符合條件的三元環。那麼總共的三元環個數很好算,就是\(C_n^3\),對於不符合條件的三元環,我們知道他們一定會有兩條邊顏色相異,而這兩條邊一定是由某個點延伸出去的,那麼我們直接列舉這個點,然後再列舉他的邊就好了(也就是列舉其他所有的點)
接下來的關鍵就是如何在一個點的所有邊中計算不合法的三元環了。為了不重複,我們對該點延伸的每個邊找在他前面的和他顏色互異的邊,然後直接加上就好了。但所需要考慮的是重複的問題,雖然對於點內的三元環來講沒有重複了,但對於點之間的三元環就可能會出現重複了,比如說對於如下三元環而言:
2到5到6是相異的,但一定會有一個點,假設是5使得5-6,5-2同色,也一定會有一個點假設是6使得6-5,6-2異色。那麼也就是一個不合法的三元環一定會重複2次計算。
那麼程式碼也就出來了。
以下是AC程式碼:
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int mac=5e3+10; bool color[mac][mac];//0為白色,1為黑色 ll pw(int x) {return 1LL*x*x;} int main(int argc, char const *argv[]) { int n; scanf ("%d",&n); int a,b,c,d,p; scanf ("%d%d%d%d%d",&a,&b,&c,&p,&d); for (int i=1; i<=n; i++){ for (int j=i+1; j<=n; j++){ ll val=(1LL*a*pw(i+j)+1LL*b*pw(i-j)+c)%p; if (val>d) {color[i][j]=color[j][i]=true;} else {color[i][j]=color[j][i]=false; } } } ll ans=1LL*n*(n-1)*(n-2)/6; ll res=0; for (int i=1; i<=n; i++){ int black=0,white=0; for (int j=1; j<=n; j++){ if (i==j) continue; if (color[i][j]) {res+=white; black++;} else {res+=black; white++;} } } ans-=res/2; printf("%lld\n",ans); return 0; }