ZOJ Problem Set - 3768 Continuous Login
Chieh
posted @ 2015年7月23日 13:47
in ZOJ
, 379 阅读
飞机票:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5231
题意:给你个数n,求最少的数,假设为a1...ak, 1+2+3...+a1+1+2+3+..a2.....+ak=n
分析:这题乍一看没有任何想法,但是我们可以暴力搜下,发现前100000最多只有3个,那么我们可以直接猜测最多只有三个,那么就可以开始搞了,先求出从1+2+。。。k>=123456789最大的n是多少,加入只有一个,直接二分查找,如果找不到,那么就尝试2个的,两个的话可以用夹逼定理,假设左边为1,右边为k,如果a1+ak>n那么就是太大了,r--,如果是<n,那么就是太小了l++,等于的话就说明2个可以,如果2个不可以,那么就三个,第一个数可以枚举,后面两个数可以用夹逼寻找,最后啪啪啪就可以AC了
/* Author:Chieh Grow up happy */ #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <queue> #include <vector> #include <map> #include <stack> #define LL long long using namespace std; int ai[16000]; int T,n; int st; void init() { scanf("%d",&n); } int l,r; bool Brsearch(int p) { l=1; r=st-1; while(l<=r) { int ok=ai[l]+ai[r]; if(ok==p)return 1; if(ok<p)l++; else r--; } return 0; } void play() { int pos=lower_bound(ai+1,ai+st,n)-ai; if(ai[pos]==n) { printf("%d\n",pos); return; } if(Brsearch(n)){ printf("%d %d\n",l,r); return; } for(int i=1;i<=n;i++){ if(n>=ai[i]&&Brsearch(n-ai[i])){ printf("%d %d %d\n",i,l,r); return; } } } int main() { st=1; LL now=0; while(now<=123456789) { now+=st; ai[st]=now; st++; } scanf("%d",&T); while(T--) { init(); play(); } return 0; }