HDU 4430 & ZOJ 3665 Yukari's Birthday(二分法+枚举)
主题链接:
HDU:http://acm.hdu.edu.cn/showproblem.php?pid=4430
ZJU:http://acm.zju.edu.cn/onlinejudge/showProblem.do?
Problem Description
Today is Yukari's n-th birthday. Ran and Chen hold a celebration party for her. Now comes the most important part, birthday cake! But it's a big challenge for them to place n candles on the top of the cake. As Yukari has lived for such a long long time, though
she herself insists that she is a 17-year-old girl.
To make the birthday cake look more beautiful, Ran and Chen decide to place them like r ≥ 1 concentric circles. They place ki candles equidistantly on the i-th circle, where k ≥ 2, 1 ≤ i ≤ r. And it's optional to place at most one candle at the center of the cake. In case that there are a lot of different pairs of r and k satisfying these restrictions, they want to minimize r × k. If there is still a tie, minimize r.
To make the birthday cake look more beautiful, Ran and Chen decide to place them like r ≥ 1 concentric circles. They place ki candles equidistantly on the i-th circle, where k ≥ 2, 1 ≤ i ≤ r. And it's optional to place at most one candle at the center of the cake. In case that there are a lot of different pairs of r and k satisfying these restrictions, they want to minimize r × k. If there is still a tie, minimize r.
Input
There are about 10,000 test cases. Process to the end of file.
Each test consists of only an integer 18 ≤ n ≤ 1012.
Each test consists of only an integer 18 ≤ n ≤ 1012.
Output
For each test case, output r and k.
Sample Input
18 111 1111
Sample Output
1 17 2 10 3 10
Source
题意:
要在一个蛋糕上放置 n 根蜡烛,摆成 r 个同心圆,每一个同心圆的蜡烛数为 k ^ i ,中间的圆心能够放一根或者不放,使得 r * k 最小,若有多个答案输出 r 最小的那个。
PS:
由于r是非常小的 !
枚举r查找k。
代码例如以下:(HDU,ZOJ上把64位换为long long就OK啦……)
#include <cstdio> #include <cmath> #include <cstring> #include <iostream> #include <algorithm> using namespace std; //typedef long long LL; typedef __int64 LL; #define ONLINE_JUDGE #ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); freopen("out.txt", "w", stdout); #endif LL n; LL findd(LL m) { LL l, r, mid; l = 2; r = n; while(l <= r) { mid = (l+r)/2; LL sum = 0, tt = 1; for(LL i = 1; i <= m; i++) { if(n/tt < mid)//注意可能溢出用除法推断一下 { //tt*mid > n sum = n+1; break; } tt*=mid; sum += tt; // if(sum > n)//防止溢出 // break; } if(sum == n-1 || sum == n) { return mid; } if(sum < n-1) { l = mid+1; } else if(sum > n) { r = mid-1; } } return -1;//没有符合的 } int main() { LL r, k, rr, kk; while(~scanf("%I64d",&n)) { rr = r = 1; kk = k = n-1; for(LL i = 2; i <= 64; i++) { LL tt = findd(i); // if(i >= n) // break; // printf("tt:%I64d>>>%I64d\n",i,tt); if(i*tt < rr*kk && tt != -1) { r = i; k = tt; rr = i; kk = tt; } } printf("%I64d %I64d\n",r,k); } return 0; } /* 18 111 1111 1022 8190 134217726 34359738366 68719476734 */
版权声明:本文博客原创文章,博客,未经同意,不得转载。