標籤:problem bool blank get sqrt long 一個 題目 define
http://codeforces.com/contest/1072/problem/C
題目大意是給出兩個數a,b ,找出若干個數p,使得 SUM{p}<=a ,找出若干個數q使得SUM{q}<=b ,還要保證找到的p和q都是不一樣的數,問|p|+|q|最大是多少。也就是要使得找的數儘可能的多。
如果不是分成兩個數a,b的話其實很簡單,答案就是 1,2,3.....x ,x是使得(x*(x+1)) <= n成立的最大值。如果拆成兩個數,那麼這個最大值顯然不會比n大。如果能看出這點來就好了,這樣我們把
資料範圍變成了sqrt(MAXA+MAXB)了。先找到這個x,其實答案就是x ,下面證明下。
已知的是x*(x+1)/2<=n=a+b (1)有一個有趣的知識是用[1,n]內的數每個數最多使用一次,一定能組成[1,(1+n)*n/2]的所有數,首先能組成[1,n],然後把n提出來與前面所有的數依次累加得到[n+1,2n-1],然後把最後兩個數提出來與前面的數依次累加得到[2n,3n-3]......由於n=a+b,所以a要麼是大於 x*(x+1)/2,這樣的話答案就是x,要麼a<=x*(x+1)/2,那麼a肯定能用一部分數完全組成,那麼剩下的數的和就是 x*(x+1)/2-a <=b (由(1)得到) ,所以b一定能裝下所有的剩下的數。
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<vector> 5 using namespace std; 6 #define LL long long 7 LL x,s,a,b; 8 bool vis[100000]; 9 void f(int n){10 vector<int>g;11 for(int i=x;i>=1;--i){12 if(!vis[i]&&i<=n){13 vis[i]=1;14 n-=i;15 g.push_back(i);16 }17 }18 cout<<g.size()<<endl;19 for(int i=0;i<g.size();++i) printf("%d%c",g[i],i==g.size()-1?‘\n‘:‘ ‘);20 }21 int main(){22 cin>>a>>b;23 s=a+b;24 LL l=0,r=100000;25 while(l<r){26 LL mid=r-(r-l)/2;27 if(mid*(mid+1)<=s*2){28 l=mid;29 }30 else{31 r=mid-1;32 }33 }34 x=l;35 f(a),f(b);36 return 0;37 }
CF-517C-思維/math