目录
1.4261孤独的照片
2.3400统计次数
3.4366堆石头
4.奶牛大学
Farmer John 最近购入了 NN 头新的奶牛,每头奶牛的品种是更赛牛(Guernsey)或荷斯坦牛(Holstein)之一。
奶牛目前排成一排,Farmer John 想要为每个连续不少于三头奶牛的序列拍摄一张照片。
然而,他不想拍摄这样的照片,其中只有一头牛的品种是更赛牛,或者只有一头牛的品种是荷斯坦牛——他认为这头奇特的牛会感到孤立和不自然。
在为每个连续不少于三头奶牛的序列拍摄了一张照片后,他把所有「孤独的」照片,即其中只有一头更赛牛或荷斯坦奶牛的照片,都扔掉了。
给定奶牛的排列方式,请帮助 Farmer John 求出他会扔掉多少张孤独的照片。
如果两张照片以不同位置的奶牛开始或结束,则认为它们是不同的。
输入格式
输入的第一行包含 N。
输入的第二行包含一个长为 N 的字符串。如果队伍中的第 i 头奶牛是更赛牛,则字符串的第 i 个字符为 G
。否则,第 i 头奶牛是荷斯坦牛,该字符为 H
。
输出格式
输出 Farmer John 会扔掉的孤独的照片数量。
数据范围
3≤N≤5×1e5
输入样例:
5
GHGHG
输出样例:
3
样例解释
这个例子中的每一个长为 33 的子串均恰好包含一头更赛牛或荷斯坦牛——所以这些子串表示孤独的照片,并会被 Farmer John 扔掉。
所有更长的子串(GHGH
、HGHG
和 GHGHG
)都可以被接受。
思路:
我一开始就是暴力解法,然后发现根本过不了..然后参照题解,结果是小学数奥..
思路其实很简单,分三种情况:
1.假设一段字符串是GGGHGG,那么以H为中心,孤独的照片就是3 * 2,即左边连续不同字符个数乘以右边连续不同字符个数
2.假设GGGGH,同样以H为参照,孤独照片个数为左边连续不同字符的个数 - 1
3.右边同理.
重点在代码实现!555我不会,所以...y总nb!
#include
using namespace std;
int n,l[500005],r[500005];
char s[500005];
long long ans;
int main()
{
cin>>n>>s;
for(int i=0,g=0,h=0;i=0;
if(s[i]=='H'){
r[i]=g;
g=0;
h++;
//printf("g=%d h=%d r[%d]=%d\n",g,h,i,r[i]);
}
else{
r[i]=h;
h=0;
g++;
//printf("g=%d h=%d r[%d]=%d\n",g,h,i,r[i]);
}
for(int i=0;i1){
long long cnt=(long long)l[i]*r[i]+max(0,l[i]-1)+max(0,r[i]-1);
ans+=cnt;
}
cout<
l [ i ]表示第i个字符左边有多少个连续不同的字符的个数;
r [ i ]表示第i个字符右边有多少个连续不同的字符的个数;
调试代码1:
5
GGHGG
g=1 h=0 l[0]=0
g=2 h=0 l[1]=0
g=0 h=1 l[2]=2
g=1 h=0 l[3]=1
g=2 h=0 l[4]=0
g=1 h=0 r[4]=0
g=2 h=0 r[3]=0
g=0 h=1 r[2]=2
g=1 h=0 r[1]=1
g=2 h=0 r[0]=0
6
调试代码2:
5
GGHHG
g=1 h=0 l[0]=0
g=2 h=0 l[1]=0
g=0 h=1 l[2]=2
g=0 h=2 l[3]=0
g=1 h=0 l[4]=2
g=1 h=0 r[4]=0
g=0 h=1 r[3]=1
g=0 h=2 r[2]=0
g=1 h=0 r[1]=2
g=2 h=0 r[0]=0
3
只能感性理解一下了..
for(int i=0;i1){
long long cnt=(long long)l[i]*r[i]+max(0,l[i]-1)+max(0,r[i]-1);
ans+=cnt;
}
这里max(0,l[i]-1)是因为如果l[i]=0的话,结果就为-1了. 最后用long long 是因为乘法可能爆int,所以要先long long,不能写成long long(l[i]*r[i]),这样就已经乘完了已经爆了.
给定两个正整数 n 和 k,求从 1 到 n 这 n 个正整数的十进制表示中 k 出现的次数。
输入格式
共一行,包含两个整数 n 和 k。
输出格式
输出一个整数,表示答案。
数据范围
1≤n≤1e6
1≤k≤9
输入样例:
12 1
输出样例:
5
样例解释
从 1 到 12 这些整数中包含 11 的数字有 1,10,11,12,一共出现了 5 次 1。
AC代码:
#include
using namespace std;
int main(){
int n,k,cnt=0;
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++){
int x=i;
while(x>0){
if(x%10==k) cnt++;
x=x/10;
}
}
printf("%d",cnt);
return 0;
}
555我只会暴力....
第2次写这个题了,害还是会忘记int x=i;
题目描述
有 NN 堆石子,每堆的石子数量分别为 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,
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
第三组数据,我们什么都不需要做。
思路:
设需要x次操作,因为每次操作石头堆数会-1,所以最终有N-x堆石头,每堆石头的数量为cnt=sum/N-x,所以我们枚举石头堆的数量N-x,必须为sum的约数。因每次输入所有 N 之和不超过 1e5,100000以内的约数大约为140个,数据量不大,可枚举。
那么我们怎么测试cnt作为每堆石头的数量满足条件?..
总共有sum个石头,这些石头被分成一堆一堆,每堆石头的数量必须为cnt,那么从第一个开始累加,如果a[i]
因为我们希望操作的次数x越少,那么石头堆的数量N-x越大,cnt=sum/N-x越小。所以一旦>cnt,说明这个cnt是不行的,cnt得再大些 且是sum的约数。
AC代码:(555我是废物...)
/*
设需要x次操作,因为每次操作石头堆数会-1,所以最终有N-x堆石头,每堆石头的数量为cnt=sum/N-x
*/
#include
using namespace std;
int t,n,sum=0;
int a[100010];
bool check(int cnt){ //cnt代表每堆石头的数量
int s=0;
for(int i=1;i<=n;i++){
s+=a[i];
if(s>cnt) return false;
if(s==cnt) s=0;
}
return true;
}
int main(){
scanf("%d",&t);
for(int i=1;i<=t;i++){
int sum=0;
scanf("%d",&n);
for(int j=1;j<=n;j++){
scanf("%d",&a[j]);
sum+=a[j];
}
for (int x=0;x<=n-1;x++){
if (sum%(n-x)== 0 && check(sum /(n-x) ) ){
printf("%d\n", x);
break;
}
}
}
return 0;
}
题目描述
Farmer John 计划为奶牛们新开办一所大学!
有 N 头奶牛可能会入学。
每头奶牛最多愿意支付 ci 的学费。
Farmer John 可以设定所有奶牛入学需要支付的学费。
如果这笔学费大于一头奶牛愿意支付的最高金额,那么这头奶牛就不会入学。
Farmer John 想赚尽可能多的钱,从而可以给他的讲师提供一笔可观的工资。
请求出他能赚到的钱的数量,以及此时应当收取多少学费。
输入格式
输入的第一行包含 N。
第二行包含 NN 个整数c1,c2,…,cN,其中 ci 是奶牛 i 愿意支付的最高学费金额。
输出格式
输出 Farmer John 可以赚到的最大金额以及最优情况下他应该收取的学费。如果有多个解,输出收取学费最小的解。
注意这个问题涉及到的整数可能需要使用 64 位整数型(例如,Java 中的 “long”,C/C++ 中的 “long long”)。
数据范围
1≤N≤105,
1≤ci≤106。
输入样例:
4
1 6 4 6
输出样例:
12 4
样例解释
如果 Farmer John 收费 4,那么 3 头奶牛将会入学,从而使他赚取 3×4=12 的金额。
思路:
将a数组排序,枚举a[i]作为收取的学费,那么赚取的金额为a[i]*(n-i+1).
AC代码
#include
#include
using namespace std;
int n,now,a[100010];
long long profit=0,ans=0;
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
sort(a+1,a+n+1);
for(int i=1;i<=n;i++){
profit=(long long)a[i]*(n-i+1);
if(ans