Discount
Accepts: 1432 Submissions: 2728
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Problem Description
学皇来到了一个餐馆吃饭。他觉得这家餐馆很好吃,于是就想办个会员。
一共有 nn 种会员充值卡套餐,假设学皇这餐饭的消费为 aa 元,选择第 ii 种套餐,需要充值 b[i] * ab[i]∗a 的钱,这次吃饭可以打 c[i]\times 10c[i]×10 折,由充值的钱支付(即这次吃饭只需要从充值金额中扣除 a\times c[i]a×c[i] 元)。以后用剩余的充值的钱吃饭不再打折。
请问学皇应该选择哪个套餐(必须选择恰好一个套餐),使得优惠的比例最大?
优惠比例的定义是把充的钱用完以后,(本来应该付的钱 - 实际付的钱) / 本来应该付的钱。在这个题目里,实际付的钱就是这次充值的花费。
Input
第一行一个整数 test(1 \leq test \leq 100)test(1≤test≤100) 表示数据组数。
对于每组数据,第一行一个正整数 n(1 \leq n \leq 100)n(1≤n≤100) 表示套餐的数目。
接下来 nn 行,每行一个正整数 b[i](1 \leq b[i] \leq 100)bi 和一个小数 c[i](0 \leq c[i] \leq 1c[i](0≤c[i]≤1,c[i]c[i] 最多包含两位小数)。
Output
对于每组数据,输出一个五位小数表示最大的优惠比例。如果小数点后超过五位,四舍五入到五位。
Sample Input
1
2
2 0.5
3 0.1
Sample Output
Copy
0.23077
样例解释
对于第一种套餐,优惠比例为 0.5a / (2a + 0.5a) = 0.2;
对于第二种套餐,优惠比例为 0.9a / (3a + 0.9a) = 9 / 39;
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
int main() {
int T,n; scanf("%d",&T);
while(T--) {
double b,c,Ans = 0;
scanf("%d",&n);
for(int i=1; i<=n; i++){
scanf("%lf %lf",&b,&c);
Ans = max(Ans,(1 - c) / (b + (1 - c)));
}
printf("%.5lf\n",Ans);
}
return 0;
}
Game
Accepts: 1381 Submissions: 2289
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Problem Description
Alice 和 Bob 在玩游戏。
桌面上有两堆金币,少的那堆有 xx 个金币,多的那堆有 2x2x 个金币。
假设金币可以被无限细分。Alice 和 Bob 事先都不知道 xx 是几,但是他们都知道 xx 是一个 (0, 1](0,1] 之间均匀分布的随机实数。
Alice 会等概率的被分配到其中的一堆金币,Bob 会得到另一堆。xx 的值和两堆金币的分配是相互独立的。
拿到金币以后,Alice 会马上数清自己拿到多少金币。然后 Alice 可以选择是否和 Bob 那堆换。
给定 Alice 拿到的金币数目,请问 Alice 要不要交换,使得她期望能得到的金币数目更多?
如果交换期望得到的金币数目多于不交换期望得到的金币数目,输出交换,否则不交换。
Input
第一行一个正整数 test~(1 \leq test \leq 200000)test (1≤test≤200000) 表示数据组数。
接下来每行一个小数 p~(0 < p \leq 2)p (0<p≤2),pp 最多保留五位小数,表示 Alice 拿到的金币数目。
Output
对于每组数据,输出 Yes 表示需要交换,输出 No 表示不要交换。
Sample Input
1
1.00000
Sample Output
Yes
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
int main() {
int T; scanf("%d",&T);
while(T--) {
double d;
scanf("%lf",&d);
if(d <= 1.00000) printf("Yes\n");
else printf("No\n");
}
return 0;
}
Permutation
Accepts: 1201 Submissions: 3277
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Problem Description
一开始有 nn 个数,他们按 1…n1…n 的顺序排列,要求交换最多 mm 对数字(同一个数字可以参与多次交换),使得逆序对数目最大。
对于一个序列 AA,如果存在正整数 i, ji,j 使得 1 \leq i < j \leq n1≤i<j≤n 而且 A[i] > A[j]A[i]>A[j],则 \lt A[i], A[j] \gt<A[i],A[j]> 这个有序对称为 AA 的一个逆序对。
Input
第一行一个正整数 test~(1 \leq test \leq 100000)test (1≤test≤100000) 表示数据组数。
对于每组数据,一行两个整数 n,m~(1 \leq n \leq 1000000, 0 \leq m \leq 1000000)n,m (1≤n≤1000000,0≤m≤1000000) 表示数字个数和最多可以交换的数字对数。
Output
对于每组数据,一行一个整数表示答案。
Sample Input
6
1 1
2 0
2 1
3 1
4 1
4 2
Sample Output
Copy
0
0
1
3
5
6
题目分析:
1……n的序列 交换一对 肯定是swap(1,n) 然后由n产生n-1个逆序对,又由于1在最后 在产生n-2个 逆序对, 然后自己推一个公式(n - 1) + (n - 2 * m)) * 2m / 2
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
// 咱也不知道为什么,n、m的数据范围其实int足够足够的
// 但是不开long long 就挂 开了就A(因为这个没有1A)
// 辛亏昨天有个题就是因为这个这才让我斗胆改成long long 又教了一遍 不然又摸不着头脑了
int main() {
int T;
long long n,m;
scanf("%d",&T);
while(T--) {
scanf("%lld %lld",&n,&m);
if(m >= n / 2) printf("%lld\n",n * (n - 1) / 2);
else {
printf("%lld\n",((n - 1) + (n - 2 * m)) * m);
}
}
return 0;
}
Intersection
Accepts: 802 Submissions: 2323
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Problem Description
Mr. Left 来到了一个路口,这个路口只能右转,并且都是两车道。
现在在南北向车道上有 nn 辆车,他们都在线 xx 南边,这些车想要通过这个路口,到东边去,具体地说,他们要开到线 yy 东边。
一辆车一个时刻可以从东南西北中选一个方向移动一个位置,或者呆在原地不动。 同一时刻同一位置不能有超过一辆车。车不能开到路外面。
在任意时刻,所有车都同时移动。两辆相邻的车不能都移动到对方的格子上。在此基础上,只要所有车移动后不存在两辆车处于同一位置,移动就合法。
问最少要多少时间,这些车才可以都开到东边?
Input
第一行一个整数 test~(1 \leq test \leq 10)test (1≤test≤10)。
对于每组数据,第一行一个整数 n~(1 \leq n \leq 100000)n (1≤n≤100000),表示车辆数目。
接下来 nn 行,每行两个整数 x,yx,y 表示车的位置,其中 xx 表示车道 idid( x=1x=1 表示右车道,x=2x=2 表示左车道),y~(1 \leq y \leq 100000)y (1≤y≤100000) 表示车在路口前第几个位置。
数据保证没有两辆车初始在同一位置。
Output
对于每组数据,一行一个整数表示答案。
Sample Input
2
2
1 1
2 1
2
1 2
2 1
Sample Output
3
4
样例解释
第一组
time 0
…
…
CC
…
time 1
…
CC…
…
…
time2
…
.CC.
…
…
time3
…
…CC
…
…
第二组
time 0
…
…
C.
.C
time 1
…
C…
.C
…
time2
C…
.C…
…
…
time3
.C…
…C.
…
…
time4
…C.
…C
…
…
//狗儿字的丑代码 就是能A
#pragma GCC optimize(3,"Ofast","inline")
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
typedef long long LL;
void read(int &x) {
x = 0;
char ch = getchar();
while (ch < '0' || ch > '9') ch = getchar();
while (ch >= '0' && ch <= '9') {x = x * 10 + ch - 48; ch = getchar();}
}
int n, c[N];
int cnt[3][N];
int pos[3][N];
void Work() {
scanf("%d", &n);
for(int i = 1; i <= n; ++i) {
int x, y;
scanf("%d%d", &x, &y);
pos[x][y] = 1;
}
int ans = 0;
for(int i = 1; i <= 100000; ++i) {
if(pos[1][i])
ans = max(ans, i + 1);
if(pos[2][i]) {
if(!pos[1][i+1]) ans = max(ans, i + 2);
else ans = max(ans, i + 3);
}
}
printf("%d\n", ans);
memset(pos,0,sizeof(pos));
}
int main () {
int t; read(t);
for(; t--; ) Work();
return 0;
}
// 又是Bug小王子加冕的一天,路过的大佬还是不要吝啬呀,不能A,
// 不能A就算了,对拍三千组没出错误
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#define Maxn 100005
using namespace std;
int a[Maxn],b[Maxn];
int main(int argc,char* argv[]) {
int T,n; scanf("%d",&T);
while(T--) {
scanf("%d",&n);
int suma = 0,sumb = 0;
for(int id,p,i=1; i<=n; i++) {
scanf("%d %d",&id,&p);
if(id == 1) b[++sumb] = p;
if(id == 2) a[++suma] = p;
}
sort(a + 1,a + suma + 1);
sort(b + 1,b + sumb + 1);
int Ans = -2147483647;
if(a[suma] == b[sumb]) Ans = max(a[suma] + 3 - 1,Ans);
else if(a[suma] - b[sumb] == -1 ) Ans = max(a[suma] - 1 + 4,Ans);
else Ans = max(max(a[suma],b[sumb]) - 1 + 2,Ans);
printf("%d\n",Ans);
}
return 0;
}
附上造数据和对拍代码
#include<cstdio>
#include<ctime>
#include<cstring>
#include<iostream>
#include<cstdlib>
using namespace std;
int vis[100005][2];
int main(int argc,char* argv[]) {
freopen("1.in","w",stdout);
srand(time(0));
int T = 1; printf("%d\n",T);
while(T--) {
int n = rand() % 1000 + 1;
printf("%d\n",n);
memset(vis,0,sizeof(vis));
int op = 1;
while(n){
int k = rand() % 1200 + 1;
while(vis[k][op]) k = rand() % 10000 + 1;
printf("%d %d\n",op,k);
vis[k][op] = 1;
n--;
if(op == 1) op = 2;
else if(op == 2) op = 1;
}
}
return 0;
}
#include<cstdio>
#include<cstring>
#include<windows.h>
using namespace std;
int main(int argc,char* argv[]) {
int T = 20000;
while(T--) {
system("data.exe");
system("std.exe");
system("main.exe" );
if(system("fc 1.out 2.out")) { printf("ERROE!"); break; }
}
return 0;
}
亲手写的Bug,而你在对岸等我勇敢,过了很久终于我愿抬头看,看了看还是没看见,
Fight
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 282 Accepted Submission(s): 68
Problem Description
Mr Left,Mr Mid,Mr Right 正在玩游戏。他们初始都有 1000 血,Mr Left,Mr Mid,Mr Right 的攻击力分别为 x,y,z。
对于每一轮,假设仍然剩下至少两个人的血量大于 0,那么选出两个血量大于 0 的人对打,他们的血量分别扣除和他们对打的另一个人的攻击力。
当有至少两个人的血量小于等于 0 时,游戏结束。
请问在最优情况下,这个游戏最少多少轮结束?
Input
第一行一个正整数 test (1≤test≤100) 表示数据组数。
接下来 test 行,每行三个正整数 x,y,z (1≤x,y,z≤1000) 表示 Mr Left, Mr Mid, Mr Right的攻击力。
Output
对于每组数据,一行一个整数表示答案。
Sample Input
2
1 1 1
1 2 3
Sample Output
1000
666
Source
2020 年百度之星·程序设计大赛 - 初赛三
题目分析:
- 枚举两两之间打了多少次,取最小,注意细节
- 官方题解:枚举Left 、Mid 和Left、Right之间打了多少轮,那么Right和Mid之间还要打多少轮是能算出来的,这样O(N^3) 直接O(N ^2)了,但是官方解法 我没写 😏
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
inline int Read(int &x) {
x = 0; char c = getchar(); int f = 1;
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while (c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
}
int main(int argc,char* argv[]) {
int T,n,m,a[3];
scanf("%d",&T);
while(T--) {
for(int i=0; i<3; i++) scanf("%d",&a[i]);
sort(a,a+3);
int x = a[1],y = a[2],z = a[0];//
int sx = 1000 / x + (1000 % x != 0),sy = 1000 / y + (1000 % y != 0),sz = 1000 / z + (1000 % z != 0);
int Ans = 3000;
for(int i=0; i<=min(sx,sy); i++){
for(int j=0; j<=min(sx,sz); j++) { // ac 打j次
int dama = y * i + j * z;
for(int k=0; k<=min(sy,sz); k++){// bc 打k次
int damb = z * k + i * x;
int damc = j * x + k * y;
int cnt = 0;
if(dama >= 1000) cnt++;
if(damb >= 1000) cnt++;
if(damc >= 1000) cnt++;
if(cnt >= 2) {// 最后应该是能出现两个人同归于尽的情况
Ans = min(Ans,i + j + k);
break;
}
}
if(dama >= 1000) break;
}
if(i * x >= 1000) break;
}
printf("%d\n",Ans);
}
return 0;
}