(有任何问题欢迎留言或私聊 && 欢迎交流讨论哦
题目链接:传送门
(题面在最下面)
(ps:终于上蓝了啊)
A. Balloons
A题的意思是把一个序列分成两部分,然后要求两部分的和不一样。
每部分必须有至少一个数。
当有解时,肯定有一种情况是这个人只选择一个数字,直接写就好了。
(第一发用了sort,果然wa了一发,还好wa了,不然就sb了)
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1005;
const int INF = 0x3f3f3f3f;
const LL mod = 1000000007;
const double eps = 1e-8;
int n;
int ar[N];
int flag;
int main(){
while(~scanf("%d",&n)){
int sum=0;
for(int i=0;i<n;++i){
scanf("%d",&ar[i]);
sum+=ar[i];
}
if(n==1){
printf("-1\n");
continue;
}
int p=-1;
for(int i=n-1;i>=0;--i){
if(ar[i]*2!=sum){
p=i;
break;
}
}
if(p==-1){
printf("-1\n");
}else{
printf("1\n%d\n",p+1 );
}
}
return 0;
}
B. Cutting
加一个隔板所需要的花费时左右数字的差的绝对值。问花费不超过k时,最多能插入多少费隔板。
On枚举,记录奇数数字和偶数数字的数量,把可以插入隔板的位置的花费加入一个数组中。然后排序,从小到大选择,直到花费超过k即可。(注意k等于0是可以插花费为0的板子)
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1005;
const int INF = 0x3f3f3f3f;
const LL mod = 1000000007;
const double eps = 1e-8;
int n,k,t;
int ar[N],br[N];
int ab(int x){
return x<0?-x:x;
}
int main(){
while(~scanf("%d%d",&n,&k)){
t=0;
for(int i=0;i<n;++i){
scanf("%d",&ar[i]);
}
int odd=0,even=0;
for(int i=0;i<n;++i){
if(ar[i]&1)odd++;
else even++;
if(odd==even&&odd>0&&i!=n-1){
br[t++]=ab(ar[i]-ar[i+1]);
}
}
sort(br,br+t);
int cnt=0;
for(int i=0;i<t;++i){
if(k>=br[i]){
cnt++;
k-=br[i];
}
}
printf("%d\n",cnt );
}
return 0;
}
C. Convert to Ones
给一段01串,有两种操作,分别花费a,b。
操作1:把一段序列倒置;操作2:把一段序列取相反数。
问最少花费使得串全为1。
预处理出0段和1段的个数。最少的花费肯定是在直接把0段执行操作2的花费 和 把所有的1段移到一段再操作2的花费之间。
贪心证明。
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 300005;
const int INF = 0x3f3f3f3f;
const LL mod = 1000000007;
const double eps = 1e-8;
int n,k,t,a,b;
char s[N];
int ar[N],br[N];
int ab(int x){
return x<0?-x:x;
}
int main(){
while(~scanf("%d%d%d",&n,&a,&b)){
scanf("%s",s);
int flag=1;
for(int i=0;i<n;++i){
ar[i]=s[i]-'0';
if(ar[i]==0)flag=0;
}
if(flag){
printf("0\n");
continue;
}
int sum=0,zero=0,one=0,last=ar[0];
if(last==1)one++;
else zero++;
for(int i=1;i<n;++i){
if(ar[i]!=last){
if(ar[i])one++;
else zero++;
last=ar[i];
}
}
LL ans=min(zero*1LL*b,(zero-1LL)*1LL*a+b);
printf("%lld\n",ans );
}
return 0;
}
D. Roman Digits
暴力搜索出1-15个罗马字母可以组成的数字的个数。
做差后发现,当n>=12时,这是一个等差数列。
然后最多不会超过50n(n<=1e9),所以不会爆longlong。
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 300005;
const int INF = 0x3f3f3f3f;
const int mod = 1000000007;
const double eps = 1e-8;
int n;
int ar[1000000+5],ans[N];
int az[6]={1,5,10,50};
void dfs(int num,int v,int t){
if(num==t){
ar[v]=1;
return;
}
for(int i=0;i<4;++i){
dfs(num+1,az[i]+v,t);
}
}
int main(){
int mm=0;
for(int t=1;t<=12;++t){
memset(ar,0,sizeof(ar));
ar[0]=1;
dfs(0,0,t);
int sum=0;
for(int k=1;k<=1000;++k){
if(ar[k]){
sum++;
mm=max(mm,k);
}
}
ans[t]=sum;
}
scanf("%d",&n);
if(n<=12){
printf("%d\n",ans[n] );
}else{
printf("%lld\n",ans[12]*1LL+(n-12)*1LL*49 );
}
return 0;
}
看到一个D题神仙代码:
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<cstdint>
#include<climits>
#include<numeric>
#include<bitset>
#include<stack>
#include<set>
#include<queue>
#include<map>
#include<cctype>
#include<string>
#include<cmath>
#include<cstring>
#include<iomanip>
#include<unordered_set>
#include<functional>
#include<iterator>
using namespace std;
long long n, wynik;
int32_t main(){
ios_base::sync_with_stdio(0);
cin.tie(0);
cin >> n;
for (int i = 0; i < 9; i++){
for (int j = 0; j <= (i < 5 ? 8 : 0); j++){
if (n - i - j >= 0) wynik += (n - i - j + 1);
}
}
cout << wynik << endl;
getchar();
getchar();
return 0;
}
题面: