CodeForces - 1501C Going Home(鸽巢原理+暴力)
題目鏈接:點擊查看
題目大意:給出 nnn 個數,問是否存在四個數滿足:a+b=c+da+b=c+da+b=c+d
題目分析:官方題解是直接 O(n2)O(n^2)O(n2) 暴力,因為每個數的范圍是 [1,2.5e6][1,2.5e6][1,2.5e6] 的,每次匹配即使會產生一個新的 sumsumsum 和,那么因為鴿巢原理,在匹配 5e65e65e6 次后,必定會產生一對 sumsumsum 相同的二元對 (i,j)(i,j)(i,j)。同理在匹配第 4?5e64*5e64?5e6 次后,一定會產生四個 sumsumsum 相同的二元對 (i,j)(i,j)(i,j)
再結合官方的證明,如果有四對 sumsumsum 相同的二元對,一定是可以組合出本題答案的
但是經過和冰哥的討論,分析出了一個更優解
首先通過移項,將原式子轉換為減法的形式:a?c=d?ba-c=d-ba?c=d?b
將求和轉換為求差,為了盡可能的不滿足題目的要求,我們需要構造類似于斐波那契數列那樣的數列,形如:
1,2,3,5,7,10,13,17,21...1,2,3,5,7,10,13,17,21...1,2,3,5,7,10,13,17,21...
就是初始時的 num=1,cnt=1num=1,cnt=1num=1,cnt=1 ,每次執行兩次 num+=cntnum+=cntnum+=cnt 后,cnt+=1cnt+=1cnt+=1
這樣構造出的數列,數學好的同學可以推公式記錄其復雜度。一般的同學看到之后也可以大膽猜測這是 n2n^2n2 級別遞增的,打個表觀察一下確實如此,當 n=5000n=5000n=5000 的時候,numnumnum 已經到達 6e66e66e6 了
所以就可以套用經典的 “小范圍暴力、大范圍猜結論” 的解題方法了,經過上述的論證+猜想,當 n>5000n>5000n>5000 的時候一定有解,且將原數列排列后,每次維護相鄰兩項的差值就可以快速獲得答案了
時間復雜度相對于官方題解來說,更趨近于線性:O(min(n2,nlogn))O(min(n^2,nlogn))O(min(n2,nlogn))
當然如果套用桶排序或基數排序的話可以將復雜度優化成線性的
代碼:
// Problem: C. Going Home // Contest: Codeforces - Codeforces Round #707 (Div. 2, based on Moscow Open Olympiad in Informatics) // URL: https://codeforces.com/contest/1501/problem/C // Memory Limit: 256 MB // Time Limit: 2000 ms // // Powered by CP Editor (https://cpeditor.org)// #pragma GCC optimize(2) // #pragma GCC optimize("Ofast","inline","-ffast-math") // #pragma GCC target("avx,sse2,sse3,sse4,mmx") #include<iostream> #include<cstdio> #include<string> #include<ctime> #include<cmath> #include<cstring> #include<algorithm> #include<stack> #include<climits> #include<queue> #include<map> #include<set> #include<sstream> #include<cassert> #include<bitset> #include<list> #include<unordered_map> #define lowbit(x) x&-x using namespace std; typedef long long LL; typedef unsigned long long ull; template<typename T> inline void read(T &x) {T f=1;x=0;char ch=getchar();while(0==isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}while(0!=isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();x*=f; } template<typename T> inline void write(T x) {if(x<0){x=~(x-1);putchar('-');}if(x>9)write(x/10);putchar(x%10+'0'); } const int inf=0x3f3f3f3f; const int N=5e6+100; int a[N]; struct Node {int x,y;Node() {}Node(int x,int y):x(x),y(y) {}bool operator!=(const Node& t) {return x!=t.x&&x!=t.y&&y!=t.x&&y!=t.y;}bool operator<(const Node& t) const {if(x!=t.x) {return x<t.x;}return y<t.y;} }node[N]; int main() { #ifndef ONLINE_JUDGE // freopen("data.in.txt","r",stdin); // freopen("data.out.txt","w",stdout); #endif // ios::sync_with_stdio(false);int n;read(n);for(int i=1;i<=n;i++) {read(a[i]);}for(int i=1;i<=n;i++) {for(int j=i+1;j<=n;j++) {int s=a[i]+a[j];if(!node[s].x) {node[s]={i,j};} else if(node[s]!=Node(i,j)) {puts("YES");cout<<i<<' '<<j<<' '<<node[s].x<<' '<<node[s].y<<endl;return 0;}}}puts("NO");return 0; }總結
以上是生活随笔為你收集整理的CodeForces - 1501C Going Home(鸽巢原理+暴力)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CodeForces - 1497D G
- 下一篇: CodeForces - 1497E2