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 i−1 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 i−1 is x, he can be at coordinate x−i, x 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.
- 1≤X≤109
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 (1≤i≤N) 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.
- 1≤N≤5000
- 1≤K≤5000
- 1≤ai≤109(1≤i≤N)
Partial Score
- 300 points will be awarded for passing the test set satisfying N,K≤400.
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;
}