题目描述
Farmer John 最近购入了 N 头新的奶牛,每头奶牛的品种是更赛牛(Guernsey)或荷斯坦牛(Holstein)之一。
奶牛目前排成一排,Farmer John 想要为每个连续不少于三头奶牛的序列拍摄一张照片。
然而,他不想拍摄这样的照片,其中只有一头牛的品种是更赛牛,或者只有一头牛的品种是荷斯坦牛——他认为这头奇特的牛会感到孤立和不自然。
在为每个连续不少于三头奶牛的序列拍摄了一张照片后,他把所有「孤独的」照片,即其中只有一头更赛牛或荷斯坦奶牛的照片,都扔掉了。
给定奶牛的排列方式,请帮助 Farmer John 求出他会扔掉多少张孤独的照片。
如果两张照片以不同位置的奶牛开始或结束,则认为它们是不同的。
输入格式
输入的第一行包含 N。
输入的第二行包含一个长为 N 的字符串。如果队伍中的第 i 头奶牛是更赛牛,则字符串的第 i 个字符为 G
。否则,第 i 头奶牛是荷斯坦牛,该字符为 H
。
输出格式
输出 Farmer John 会扔掉的孤独的照片数量。
数据范围
3 ≤ N ≤ 5×1e5
输入样例
5
GHGHG
输出样例
3
样例解释
这个例子中的每一个长为 3 的子串均恰好包含一头更赛牛或荷斯坦牛——所以这些子串表示孤独的照片,并会被 Farmer John 扔掉。
所有更长的子串(GHGH
、HGHG
和 GHGHG
)都可以被接受。
具体实现
#include
using namespace std;
typedef long long LL;
const int N = 500010;
int n;
char str[N];
//L[N]表示左边有多少个跟当前位置不同的字母
//R[N]表示右边有多少个跟当前位置不同的字母
int L[N], R[N];
int main()
{
cin >> n;
cin >> str;
//左边
for (int i = 0, h = 0, g = 0; i < n; i ++ )
{
if (str[i] == 'G')
{
L[i] = h;
h = 0;
g ++;
}
else
{
L[i] = g;
g = 0;
h ++;
}
}
//右边
for (int i = n - 1, h = 0, g = 0; i >= 0; i -- )
{
if (str[i] == 'G')
{
R[i] = h;
h = 0;
g ++;
}
else
{
R[i] = g;
g = 0;
h ++;
}
}
LL res = 0;
for (int i = 0; i < n; i ++ )
{
res += (LL)L[i] * R[i] + max(L[i] - 1, 0) + max(R[i] - 1, 0);
}
cout << res;
system("pause");
return 0;
}
题目描述
给定两个正整数 n 和 k,求从 1 到 n 这 n 个正整数的十进制表示中 k 出现的次数。
输入格式
共一行,包含两个整数 n 和 k。
输出格式
输出一个整数,表示答案。
数据范围
1 ≤ n ≤ 1e6
1 ≤ k ≤ 9
输入样例
12 1
输出样例
5
样例解释
从 1 到 12 这些整数中包含 1 的数字有 1,10,11,12,一共出现了 5 次 1。
具体实现
#include
using namespace std;
int main()
{
int n, k;
cin >> n >> k;
int res = 0;
for (int i = 1; i <= n; i ++ )
{
for (int j = i; j; j /= 10)
{
if (j % 10 == k)
{
res ++ ;
}
}
}
cout << res << endl;
system("pause");
return 0;
}
题目描述
有 N 堆石子,每堆的石子数量分别为 a1,a2,…,aN。
你可以对石子堆进行合并操作,将两个相邻的石子堆合并为一个石子堆,例如,如果 a=[1,2,3,4,5],合并第 2,3 堆石子,则石子堆集合变为 a=[1,5,4,5]。
我们希望通过尽可能少的操作,使得石子堆集合中的每堆石子的数量都相同。
请你输出所需的最少操作次数。
本题一定有解,因为可以将所有石子堆合并为一堆。
输入格式
第一行包含整数 T,表示共有 T 组测试数据。
每组数据第一行包含整数 N。
第二行包含 N 个整数 a1,a2,…,aN。
输出格式
每组数据输出一行结果。
数据范围
1 ≤ T ≤ 10
1 ≤ N ≤ 1e5
0 ≤ ai ≤ 1e6
从 i=1 到 i=n 的 ai 之和 ≤ 1e6
每个输入所有 N 之和不超过 1e5
输入样例
3
6
1 2 3 1 1 1
3
2 2 3
5
0 0 0 0 0
输出样例
3
2
0
样例解释
第一组数据,只需要用 3 个操作来完成:
1 2 3 1 1 1
-> 3 3 1 1 1
-> 3 3 2 1
-> 3 3 3
第二组数据,只需要用 2 个操作来完成:
2 2 3
-> 2 5
-> 7
第三组数据,我们什么都不需要做。
具体实现
#include
using namespace std;
const int N = 100010;
int n;
//w[N]表示每堆石子的数量
int w[N];
bool check(int cnt)
{
//s表示这一段石子的数量
for (int i = 0, s = 0; i < n; i ++ )
{
s += w[i];
//如果s大于cnt,就直接返回false,开始枚举下一个
//如果s等于cnt,就将其置为0,最后返回true,表明可以实现。
if (s > cnt)
{
return false;
}
if (s == cnt)
{
s = 0;
}
}
return true;
}
int main()
{
int T;
cin >> T;
while (T -- )
{
cin >> n;
int sum = 0;
for (int i = 0; i < n; i ++ )
{
cin >> w[i];
sum += w[i];
}
for (int i = n; i; i -- )
{
if (sum % i == 0 && check(sum / i))
{
cout << n - i << endl;
break;
}
}
}
system("pause");
return 0;
}
题目描述
北京大学对本科生的成绩施行平均学分绩点制(GPA)。
既将学生的实际考分根据不同的学科的不同学分按一定的公式进行计算。
公式如下:
实际成绩 | 绩点 |
---|---|
90——100 | 4.0 |
85——89 | 3.7 |
82——84 | 3.3 |
78——81 | 3.0 |
75——77 | 2.7 |
72——74 | 2.3 |
68——71 | 2.0 |
64——67 | 1.5 |
60——63 | 1.0 |
60以下 | 0 |
一门课程的学分绩点 = 该课绩点 × 该课学分
总评绩点 = 所有学科学分绩点之和 / 所有课程学分之和
现要求你编写程序求出某人 A 的总评绩点(GPA)。
输入格式
第一行,总的课程数 n;
第二行,相应课程的学分(两个学分间用空格隔开);
第三行,对应课程的实际得分;
此处输入的所有数字均为整数。
输出格式
输出有一行,总评绩点,精确到小数点后 2 位小数。
数据范围
1 ≤ n ≤ 10
学分取值范围 [1,10]
课程得分范围 [0,100]
输入样例
5
4 3 4 2 3
91 88 72 69 56
输出样例
2.52
具体实现
#include
,输出语句使用如下前缀 cout << fixed << setprecision(2)
,括号中表示保留小数的位数。#include
using namespace std;
const int N = 20;
int key[10] = {0, 60, 64, 68, 72, 75, 78, 82, 85, 90};
double value[10] = {0, 1.0, 1.5, 2.0, 2.3, 2.7, 3.0, 3.3, 3.7, 4.0};
//a[N]表示相应课程的学分
//b[N]对应课程的实际得分
int a[N], b[N];
double get(int x)
{
for (int i = 9; i >= 0; i -- )
{
if (x >= key[i])
{
return value[i];
}
}
return 0;
}
int main()
{
int n;
cin >> n;
for (int i = 0; i < n; i ++ )
{
cin >> a[i];
}
for (int i = 0; i < n; i ++ )
{
cin >> b[i];
}
double sum = 0, cnt = 0;
for (int i = 0; i < n; i ++ )
{
sum += get(b[i]) * a[i];
cnt += a[i];
}
cout << fixed << setprecision(2) << sum / cnt;
system("pause");
return 0;
}
题目描述
Farmer John 计划为奶牛们新开办一所大学!
有 N 头奶牛可能会入学。
每头奶牛最多愿意支付 ci 的学费。
Farmer John 可以设定所有奶牛入学需要支付的学费。
如果这笔学费大于一头奶牛愿意支付的最高金额,那么这头奶牛就不会入学。
Farmer John 想赚尽可能多的钱,从而可以给他的讲师提供一笔可观的工资。
请求出他能赚到的钱的数量,以及此时应当收取多少学费。
输入格式
输入的第一行包含 N。
第二行包含 N 个整数 c1,c2,…,cN,其中 ci 是奶牛 i 愿意支付的最高学费金额。
输出格式
输出 Farmer John 可以赚到的最大金额以及最优情况下他应该收取的学费。如果有多个解,输出收取学费最小的解。
注意这个问题涉及到的整数可能需要使用 64 位整数型(例如,Java 中的 “long”,C/C++ 中的 “long long”)。
数据范围
1 ≤ N ≤ 1e5
1 ≤ ci ≤ 1e6
输入样例
4
1 6 4 6
输出样例
12 4
样例解释
如果 Farmer John 收费 4,那么 3 头奶牛将会入学,从而使他赚取 3×4=12 的金额。
具体实现
#include
using namespace std;
typedef long long LL;
const int N = 100010;
int n;
int w[N];
int main()
{
cin >> n;
for (int i = 0; i < n; i ++ )
{
cin >> w[i];
}
//将所有牛愿意交的学费按从小到大排序
sort(w, w + n);
//将总金额和入学费用初始化为0
LL rtot = 0, rfee = 0;
for (int i = 0; i < n; i ++ )
{
//该点的总金额
LL tot = (LL)w[i] * (n - i);
//如果有两个总金额相同的,我们要输出收学费少的。
//因此,可以直接略去。
//因为,学费是按从小到大排列,在左边的学费自然比在右边的学费少。
if (tot > rtot)
{
rtot = tot;
rfee = w[i];
}
}
cout << rtot << " " << rfee << endl;
system("pause");
return 0;
}