Toy Sum(codeforces)

来源:互联网 发布:nginx隐藏真实ip 编辑:程序博客网 时间:2024/05/17 22:04


题目大意:

   从1-1000000中选取n个数,组成一个集合X,然后

在剩余的数中寻找到m个数,组成集合Y,使其满足:

                   (s=1000000)

解题思路:

   一般这种在没有思路的时候,我们最先想到的是模拟,然后在模拟的过程中进行优化。

先列出我模拟的代码:

#include <cstdio>

#include <algorithm>

#define INF 1000000

const int maxn=1000000+10;

using namespace std;

bool a[maxn];

int n;

bool xz(long long  m,long long sum,long long  q){ //选取m代表前m-1个数已经选取过了,sum代                                             表还剩下的和 q代表已经选取的数个数;

  if (q>INF-n) return false;          //如果q+n>INF 不满足情况 退出

  for (long long i=m;i<=1000000;i++){

    if (a[i]==false&&sum+i-INF==0) {

      printf("%I64d\n",q);

      printf("%I64d ",i);

      return true;

    }

    if (!a[i]&&sum+i-INF>0){

      a[i]=true;

      if (xz(i+1,sum+i-INF,q+1)){

         printf("%I64d ",i);

         return true;

      }

      a[i]=false;

    }

    if (!a[i]&&sum+i-INF<0) {      //使用二分法加快求解

      long long L,R;

      L=i;R=INF;

      while (L<R){

        long long  mid=(L+R)/2;

        if (sum+mid-INF<0) L=mid+1;

        else R=mid;

      }

      i=L-1;

    }

  }

  return false;

}

int main (){

  long long sum;

  while(scanf("%d",&n)!=EOF){

    sum=0;

    for (int i=1;i<=n;i++) a[i]=false;

    for (int i=0;i<n;i++){

      long long b;

      scanf("%I64d",&b);

      a[b]=true;

      sum+=b-1;

    }

    xz(1,sum,1);

    printf("\n");

  }

  return 0;

}

但是不过如何优化,使用模拟的方法这题我都没过去(如果你有模拟过的,请告诉我);

   但是仔细分析后,发现这题有规律。

就以s=8 为例

     1   2   3   4   5   6   7   8

 X   0   1   2   3   4   5   6   7

 Y   7   6   5   4   3   2   1   0

上图所示的是全集中的数在X与在Y中的值为多少;

   聪明的你应该想到方法了吧!

   对于一个在X中的数ii<=500000)如果(1000001-i)没有在X中,我们就选择它。如果在了,我们就选择一组

i)与(1000001-i)都没有在X中的数。

 

我的代码:

#include <cstdio>

#include <algorithm>

#define INF 1000000

using namespace std;

const int maxn = 1000001;

bool a[maxn];

int  b[maxn/2];

int main (){

  int n,m=0;

  while (scanf("%d",&n)!=EOF){

    for (int i=1;i<=n;i++) a[i]=false;

    for (int i=0;i<n;i++){

       int b;

       scanf("%d",&b);

       a[b]=true;

    }

    int ans=0,q=0,m=0;

    for (int i=1;i<=INF/2;i++){

      if (a[i]&&a[INF+1-i]) q++;

      if (q&&!a[i]&&!a[INF+1-i]) {

        a[i]=a[INF+1-i]=true;

        b[m++]=i;

        b[m++]=INF+1-i;

        q--;

        n-=2;

        ans+=2;

      }

      if (a[i]&&!a[INF+1-i]) {n--;a[INF+1-i]=true;b[m++]=INF+1-i;ans++;}

      if (!a[i]&&a[INF+1-i]) {n--;a[i]=true;b[m++]=i;ans++;}

      if (!n) break;

    }

    if (n){

      for (int i=1;i<=INF/2;i++){

        if (q&&!a[i]&&!a[INF+1-i]) {

          a[i]=a[INF+1-i]=true;

          b[m++]=i;

          b[m++]=INF+1-i;

          q--;

          n-=2;

          ans+=2;

        }

        if (!q) break;

      }

    }

    printf("%d\n",ans);

    for (int i=0;i<m;i++)

      printf("%d ",b[i]);

    printf("\n");

  }

  return 0;

}

0 0
原创粉丝点击