zoukankan      html  css  js  c++  java
  • CF-517C-思维/math

    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?'
    ':' ');
    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 }
  • 相关阅读:
    POJ 3669 Meteor Shower(bfs)
    MongoDB 分片的原理、搭建、应用
    Linux下Mongodb安装和启动配置
    目录操作
    一阶段第四次整理(关于滚动条监听的进一步解释)
    HTML DOM 节点介绍(nodeName,nodeValue,nodeType)
    ASP.NET 开发人员应该知道的8个网站
    Java 里快如闪电的线程间通讯
    php-多态
    Winform控件学习-TreeView
  • 原文地址:https://www.cnblogs.com/zzqc/p/9844270.html
Copyright © 2011-2022 走看看