CF-517C-思維/math

來源:互聯網
上載者:User

標籤: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

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.