A - Olympic Ranking

题意:n支队伍,各有一定数量的金牌,银牌,铜牌。按照金牌 > 银牌 > 铜牌的优先级,找出最强的队伍。

题解:题意简单,难点在于输入那个字符串。
<1> 使用 getline和 string配合,然后输出的时候从第 1位输出而不是第 0位,会 wa12。
<2> 我是手写了一个输入字符串的函数。
<3> 我队友用的 map + tuple + string,也把代码附上,可以做个参考。(%%%

代码:**<2>**

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include<bits/stdc++.h>
using namespace std;

#define endl "\n"
#define ll long long
#define inf 0x3f3f3f3f
#define infll 1e15+7
#define IOS ios::sync_with_stdio(0); cin.tie(0)
#define debug(a) cout<<"*****\tdebug: "<<a<<"\t*****"<<endl;
const double eps = 1e-7;
const double pi = acos(-1.0);
const int mod = 1e9+7;
const int N = 5 + 1e3;

void getstr(char s[], int Lim)
{
int i = 0;
char ch = getchar();
while(ch == ' ') ch = getchar();
while(ch != '\n' && ch != EOF && i < Lim)
{
s[i++] = ch;
ch = getchar();
}
s[i] = 0;
}

int a[N], b[N], c[N];
char s[310][100000];

int main()
{
#ifndef ONLINE_JUDGE
freopen("in.in", "r", stdin);
freopen("out.out", "w", stdout);
#endif
// IOS;
// ---------------------------------------------------------------
int n; cin>>n;
for(int i = 1; i <= n; i++)
{
cin>>a[i]>>b[i]>>c[i];
getstr(s[i], 100000);
}
int ans = 1;
for(int i = 2; i <= n; i++)
if((a[i] > a[ans]) || (a[i] == a[ans] && b[i] > b[ans]) || (a[i] == a[ans] && b[i] == b[ans] && c[i] > c[ans]))
ans = i;
printf("%s", s[ans]);
return 0;
}

代码:<3>
在这里插入图片描述

B - Aliquot Sum

题意:求一个数的因子之和(除了自己本身),然后和自身比大小,对应输出三种字符串。

题解:预处理一下即可。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include<bits/stdc++.h>
using namespace std;

#define endl "\n"
#define ll long long
#define inf 0x3f3f3f3f
#define infll 1e15+7
#define IOS ios::sync_with_stdio(0); cin.tie(0)
#define debug(a) cout<<"*****\tdebug: "<<a<<"\t*****"<<endl;
const double eps = 1e-7;
const double pi = acos(-1.0);
const int mod = 1e9+7;
const int N = 5 + 1e6;

ll ans[N];

int main()
{
#ifndef ONLINE_JUDGE
freopen("in.in", "r", stdin);
freopen("out.out", "w", stdout);
#endif
// IOS;
// ---------------------------------------------------------------
for(int i = 1; i < 1000010; i++)
for(int j = 2*i; j < 1000010; j += i)
ans[j] += i;
// for(int i = 1; i <= 20; i++) cout<<ans[i]<<endl;
int T; cin>>T;
while(T--)
{
int x; cin>>x;
if(ans[x] > x) cout<<"abundant"<<endl;
else if(ans[x] == x) cout<<"perfect"<<endl;
else cout<<"deficient"<<endl;
}
return 0;
}

C - A Sorting Problem

题意:给定一个数组,求逆序对数。

题解:板子题,树状数组跑一遍即可。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#include<bits/stdc++.h>
using namespace std;

#define endl "\n"
#define ll long long
#define inf 0x3f3f3f3f
#define infll 1e15+7
#define IOS ios::sync_with_stdio(0); cin.tie(0)
#define debug(a) cout<<"*****\tdebug: "<<a<<"\t*****"<<endl;
const double eps = 1e-7;
const double pi = acos(-1.0);
const int mod = 1e9+7;
const int N = 5 + 1e6;


int n;
int tree[N], f[N];
struct node
{
int x, idx;
}a[N];

bool cmp(node a, node b)
{
return a.x < b.x;
}

int lowbit(int i)
{
return i & -i;
}

void update(int pos, int val)
{
for(int i = pos; i <= n; i += lowbit(i))
tree[i] += val;
}

int ask(int pos)
{
int res = 0;
for(int i = pos; i > 0; i -= lowbit(i))
res += tree[i];
return res;
}

int main()
{
#ifndef ONLINE_JUDGE
freopen("in.in", "r", stdin);
freopen("out.out", "w", stdout);
#endif
IOS;
// ---------------------------------------------------------------
cin>>n;
for(int i = 1; i <= n; i++)
{
cin>>a[i].x;
a[i].idx = i;
}
sort(a+1, a+n+1, cmp);

f[a[1].idx] = 1;
for(int i = 2; i <= n; i++)
{
if(a[i].x != a[i-1].x) f[a[i].idx] = i;
else f[a[i].idx] = f[a[i-1].idx];
}
ll ans = 0;
for(int i = 1; i <= n; i++)
{
update(f[i], 1);
ans += i - ask(f[i]);
}
cout<<ans<<endl;
return 0;
}

D - Drunk Passenger

题意:n个人按照先后顺序上飞机坐座位,第一个人喝醉了,所以他会等可能地坐到除了自己位置之外的位置上。剩下的乘客,如果自己的位置被占了,就会等可能的坐到其他位置上,否则坐自己的位置。求最后一个人做对位置的概率。

题解:【醉汉、1、2、3 ……n-2、最后一个人】 分两种大情况:

<1> 醉汉先坐你的位置($1/(n-1)$)
那么最后一个人坐错位置的概率为 $1*(1/(n-1))$ = $1/(n-1)$,则坐对位置的概率也为$1/(n-1)$。

<2> 醉汉坐其他人的位置 ( $(n-2)/(n-1)$ )
假如醉汉坐到了第 x个人的位置,那么从第 2个到第 x-1个人都会坐到自己的位置上。然后剩下的位置第 x个人都可以坐。
或者说情况就变成了:一共 m个人,m个位置(m = n-x+1),每个人都等概率坐任意位置(但还保持那种坐自己位置的特性)。那么最后一个人坐到最后一个位置上的概率就是 1/2(这是个经典的醉汉问题,或者说疯子问题,这里挂一个知乎的链接,就是关于这个问题的若干个解释,不再给出证明知乎醉汉上飞机问题链接

这种情况下,最后一个人坐对位置的概率就是$(1/2) * ((n-2)/(n-1))$

那么两种情况相加一下,就是 $1/(n-1)$ + $(1/2) * ((n-2)/(n-1))$ = $n/(2*(n-1))$

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include<bits/stdc++.h>
using namespace std;

#define endl "\n"
#define ll long long
#define inf 0x3f3f3f3f
#define infll 1e15+7
#define IOS ios::sync_with_stdio(0); cin.tie(0)
#define debug(a) cout<<"*****\tdebug: "<<a<<"\t*****"<<endl;
const double eps = 1e-7;
const double pi = acos(-1.0);
const int mod = 1e9+7;
const int N = 5 + 1e6;

int main()
{
#ifndef ONLINE_JUDGE
freopen("in.in", "r", stdin);
freopen("out.out", "w", stdout);
#endif
IOS;
// ---------------------------------------------------------------
int n; cin>>n;
double ans = 1.0*n/(2*(n-1));
cout<<ans;
return 0;
}

E - Eatcoin

题意:简单地说,在第 d天,花费 p块钱,生产 $q*d^5$块钱。 生产到 $10^{99}$ 块钱算富豪。每天必须先花费 p块钱才能生产。求开始时最少需要有多少钱,以及在开始时有需要的最少钱的情况下,最少需要多少天才能变成富豪。

题解:首先要推出 $1^5 + 2^5 + 3^5 + …+n^5$的公式为:$(n^2*(n+1)^2*(2n^2 + 2n-1)) / 12$
用那个组合数的公式应该也可以(公式证明链接

<1> 求开始最少需要多少钱
刚开始花的钱的多,之后生产的钱多。假如到第 x天,生产的钱的总和大于等于花费的钱的总和。所以答案为,前x-1天花费总数 - 前x-1天生产总数 + 第 x天的花费

<2> 求最少需要多少天
列出求手上钱的总数的式子,然后二分天数即可。

代码:(python版本, c++版本的大数写的一直有问题,还在debug)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
def cal(n, p, q, x):
return q*(n*n)*(n+1)*(n+1)*(2*n*n+2*n-1)//12 - p*n + x

p, q = map(int, input().split())
last = p - q
i = 2
while(1):
now = i*p-q*(i*i)*(i+1)*(i+1)*(2*i*i+2*i-1)//12
i += 1
if now >= last:
last = now
else:
print(last+p) #下一次需要先消耗
break

l = 1
r = 10**100
ans = 0
x = last+p # 不要x也能过,答案太大,x没影响?
while l <= r:
mid = (l+r)//2
if cal(mid, p, q, x) < 10**99:
l = mid+1
else:
r = mid-1
ans = mid
print(ans)

J - JavaScript

题意:模拟 javascript的减法运算。给定两个字符串a b,如果字符串中存在非数字的元素,输出 NaN。否则将两个字符串转为数字,进行相减运算。

题解:简单模拟即可。(0对应的 ASCLL值为 48)

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include<bits/stdc++.h>
using namespace std;

#define endl "\n"
#define ll long long
#define inf 0x3f3f3f3f
#define infll 1e15+7
#define IOS ios::sync_with_stdio(0); cin.tie(0)
#define debug(a) cout<<"*****\tdebug: "<<a<<"\t*****"<<endl;
const double eps = 1e-7;
const double pi = acos(-1.0);
const int mod = 1e9+7;
const int N = 5 + 1e3;

int main()
{
#ifndef ONLINE_JUDGE
freopen("in.in", "r", stdin);
freopen("out.out", "w", stdout);
#endif
// IOS;
// ---------------------------------------------------------------
string a, b; cin>>a>>b;
bool falg = 0;
for(int i = 0; i < a.size(); i++)
if(!isdigit(a[i]))
falg = 1;
for(int i = 0; i < b.size(); i++)
if(!isdigit(b[i]))
falg = 1;
if(falg) cout<<"NaN";
else
{
int ans1 = 0, ans2 = 0;
for(int i = 0; i < a.size(); i++) ans1 = ans1*10 + a[i] - 48;
for(int i = 0; i < b.size(); i++) ans2 = ans2*10 + b[i] - 48;
cout<<ans1-ans2;
}
return 0;
}