训练赛后补题 02
2020-06-29 个人训练赛后补题

这题比赛上被我跳了……跳了,好的吧。
一开始我以为题目的意思是:小猪先拿了k个币,然后两人轮流拿一成剩下的(向下取整),我就纳闷了,向下取整到0~9个金币咋整?
然后在即将询问出题人之际脑子终于活过来:哦,是小猪每次取k,小羊每次取一成啊,得,下面是脑子活过来后写的代码:
Time limit exceeded on test 7
超时代码:
1 #pragma warning (disable:4996) 2 #include <iostream> 3 #include<algorithm> 4 #include<stdio.h> 5 #include<math.h> 6 #include<string.h> 7 #include<string> 8 #define MAX1 100005 /*1e5 + 5*/ 9 #define MAX2 1000000005 /*le9 + 5*/ 10 #define MAX3 200005 /*1e5 + 5*/ 11 #define T2 27 12 #define T3 18 13 using namespace std; 14 typedef long long int ll; 15 #define MOL 998244353 16 17 int main() { 18 ll n, k,t,nt; 19 while (scanf("%lld", &n) != EOF) { 20 for (k = 1; k < n; ++k) { 21 nt = n; 22 t = 0; 23 while (nt > k) { 24 nt -= k; 25 nt -= nt / 10; 26 t++; 27 } 28 nt += k * t; 29 if (nt >= n - nt)break; 30 } 31 printf("%lld\n", k); 32 } 33 return 0; 34 }
分析一下,时间复杂度n^2大概承受不住1e18这么大的数据
然后又发现实际上每个k对应n有一定的范围,要是硬应付timelimit暴力撞库不是不可以……
但是毕竟是补题。
化简思路:k从大入手不划算,从小入手复杂度太大,那就从中间;取中间值,k使小猪胜利就继续取前区间中值,不能就取后区间中值。
最终AC代码:
1 #pragma warning (disable:4996) 2 #include <iostream> 3 #include<algorithm> 4 #include<stdio.h> 5 #include<math.h> 6 #include<string.h> 7 #include<string> 8 #define MAX1 100005 /*1e5 + 5*/ 9 #define MAX2 1000000005 /*le9 + 5*/ 10 #define MAX3 200005 /*1e5 + 5*/ 11 #define T2 27 12 #define T3 18 13 using namespace std; 14 typedef long long int ll; 15 #define MOL 998244353 16 17 int ispig_wim(ll n, ll k) { 18 ll t = 0; 19 ll nt = n; 20 while (nt > k) { 21 nt -= k; 22 nt -= nt / 10; 23 t++; 24 } 25 nt += k * t; 26 if (nt >= n - nt)return 1; 27 return 0; 28 } 29 int main() { 30 ll n, k; 31 while (scanf("%lld", &n) != EOF) { 32 ll low = 1, high = n, mid = (low + high) / 2; 33 while (low < high) { 34 if (ispig_wim(n, mid)) 35 high = mid; 36 else 37 low = mid + 1; 38 mid = (high + low) / 2; 39 } 40 k = mid; 41 printf("%lld\n", k); 42 } 43 return 0; 44 }
我不该跳过这一题的,别问,问就是后悔

浙公网安备 33010602011771号