atcoder 1th C

C - Go Home


Time limit : 2sec / Memory limit : 256MB

Score : 200 points

Problem Statement

There is a kangaroo at coordinate 0 on an infinite number line that runs from left to right, at time 0. During the period between time i1 and time i, the kangaroo can either stay at his position, or perform a jump of length exactly i to the left or to the right. That is, if his coordinate at time i1 is x, he can be at coordinate xix or x+i at time i. The kangaroo's nest is at coordinate X, and he wants to travel to coordinate X as fast as possible. Find the earliest possible time to reach coordinate X.

Constraints

  • X is an integer.
  • 1X109

Input

The input is given from Standard Input in the following format:

X

Output

Print the earliest possible time for the kangaroo to reach coordinate X.

先上自己的错误的代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<string>
#include<cstring>
#include<iomanip>
#include<iostream>
#include<stack>
#include<cmath>
#include<map>
#include<vector>
#define ll long long
#define inf 0x3f3f3f3f
#define bug1 cout<<"bug1"<<endl;
#define bug2 cout<<"bug2"<<endl;
#define bug3 cout<<"bug3"<<endl;
using namespace std;
long long  sum[33005];
int main(){
    sum[1]=1;
    for(int i=2;i<=33000;++i)
        sum[i]+=sum[i-1]+i;
    long long x;
    cin>>x;
    ll rpos=upper_bound(sum+1,sum+1+33000,x)-sum-1;
 
    ll gap=x-sum[rpos];
    if(x==1)cout<<1<<'\n';
    else if(gap==0)cout<<rpos<<'\n';
    else cout<<rpos+1<<'\n';
 
}
大神的代码;
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<string>
#include<cstring>
#include<iomanip>
#include<iostream>
#include<stack>
#include<cmath>
#include<map>
#include<vector>
#define ll long long
#define inf 0x3f3f3f3f
#define bug1 cout<<"bug1"<<endl;
#define bug2 cout<<"bug2"<<endl;
#define bug3 cout<<"bug3"<<endl;
using namespace std;
long long  sum[33005];
int main(){
    long long x;
    cin>>x;
    ll l=0,r=1e9;
    while((l+1)<r){//二分的是走的步数
        ll mid=(l+r)>>1;
        ll tmp=(mid+1)*mid/2+(mid+1)*mid%2;//原来是二分。。自己一直没有看出来
                    //tmp表示的是将要到的位置
        if(tmp>=x){//如果位置比x大,如果。。 就。
            r=mid;//二分的依据是。。(不太清楚
        }
        else {
            l=mid;
        }
    }
    cout<<r<<'\n';

}

D - No Need


Time limit : 2sec / Memory limit : 256MB

Score : 600 points

Problem Statement

AtCoDeer the deer has N cards with positive integers written on them. The number on the i-th card (1iN) is ai. Because he loves big numbers, he calls a subset of the cards good when the sum of the numbers written on the cards in the subset, is K or greater.

Then, for each card i, he judges whether it is unnecessary or not, as follows:

  • If, for any good subset of the cards containing card i, the set that can be obtained by eliminating card i from the subset is also good, card i is unnecessary.
  • Otherwise, card i is NOT unnecessary.

Find the number of the unnecessary cards. Here, he judges each card independently, and he does not throw away cards that turn out to be unnecessary.

Constraints

  • All input values are integers.
  • 1N5000
  • 1K5000
  • 1ai109(1iN)

Partial Score

  • 300 points will be awarded for passing the test set satisfying N,K400.

Input

The input is given from Standard Input in the following format:

N K
a1 a2 ... aN

Output

Print the number of the unnecessary cards.

题意:求出不需要的数字的个数:       题目给出了 ”不需要的数”的定义
不太理解代码,先写一点理解:不过我的理解很可能是不对的。。  
希望大神能给透彻点的算法思想。。
#include<iostream>
#include<cstdio>
#include<cstring>
//#include<vector>
#include<algorithm>
 
 
#ifdef L_JUDGE
#pragma warning(disable:4996)
#endif
 
using namespace std;
const int MAXN=5e3+10;
 
int N,K;
int len,a[MAXN];
 
 
int main(){
	#ifdef L_JUDGE
		freopen("in.txt","r",stdin);
//		freopen("out.txt","w",stdout);
	#endif
 
    cin>>N>>K;
    len=0;
    int ans=N;
    for(int i=1;i<=N;i++){
         int x;
         cin>>x;
         if(x>=K){//如果是>=k的,那么他自己可以成为一个子集, 他不能去掉,所以ans--
             ans--;
         }else{
             a[len++]=x;
         }
    }
    sort(a,a+len);
    int tmp=0;
    while(len>=2){
    /*    for(int i=1;i<ni;i++){
            tmp+=a[len-i];
        }*/
        tmp+=a[len-1];
        if(a[len-2]+tmp<K){//先拿刚开始的循环看,如果最大的两个数都没有大于K,那么说明应该找最大的3个数如果还不成立,继续循环
            len--;//对应于后面的ans=ans-(len-r); ,说明最后面的这几个数可以是不需要的。因为这个数
	    continue;
        }        if(a[0]+tmp>=K){//如果最后面的一些数字(经过前面的筛选,已经是>=K的了)加上最小的那个数>=K,说明(那么对于a[0], a[len-1],a[len-2]都是不能够去掉的,中间的数字就更不能去掉了,所以ans=0;
            ans=0;//表示tmp+a[len-2]>=K,   tmp+a[0]>=K,  那么他们都不能去掉。。
             break;
        }
        int l=0,r=len-2;
        while(l+1<r){
             int mid=(l+r)/2;//二分寻找数列中的某个数,使得这个数满足下面条件
             if(tmp+a[mid]>=K){//这个数与最后面的一些数字相加>=K,
                 r=mid;
             }else{
                 l=mid;
             }
        }
 	这个与a[0]+tmp>=K是一样的,或者说,a[0]+tmp>=K是一种优化(或是特殊,当r=0并且没有进行len--操作的时候)
        ans=ans-(len-r);//ans=ans-(len-r+1)+1;  这应该是原式,就是把mid以及后面的数字去掉后(因为这些数字是不能去掉的,他们组成集合之后必有从mid~len中去掉一个数就会不满足条件  原来数列的长度,
        len=r;//然后再来循环
    }
    cout<<ans<<endl;
 
	#ifdef L_JUDGE
		fclose(stdin);
		fclose(stdout);
//		system("out.txt");
	#endif
 
	return 0;
}

 
   

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值