题目链接:http://codeforces.com/contest/867
只补了四道题。
A题:简单模拟即可,分别计算S->F,F->S的次数,然后比较。
#include<stdio.h>
const int maxn=110;
char a[maxn];
int main(){
int n;
scanf("%d",&n);
scanf("%s",a);
int sf=0,fs=0;
bool f;
if(a[0]=='S') f=true;
else f=false;
for(int i=1;i<n;i++){
if(a[i]=='S'){
if(1&f==0) fs++;
f=true;
}
else if(a[i]=='F'){
if(1&f) sf++;
f=false;
}
}
if(sf>fs) printf("YES\n");
else printf("NO\n");
return 0;
}
B:题意大概是,给你一个零钱总数n,再给你m钟面值,然后列出m种面值,求出用m种面值的钱组成n的方案数目(每一种面值可以用任意次)。这题反过来,给你一个方案数目,自己给出总数n,和面值数m,以及m种面值。必然有规律,不然太麻烦了……,毕竟太多不确定的变量.
找规律,我们设置金额为n,方案数为a.
n=1, 1=1, a=1
n=2 2=2,2=1+1 a=2;
n=3 3=2+1=1+1+1 a=2;
n=4 4=2+2=1+1+2=1+1+1+1 a=3
n=5 5=2+2+1=1+1+2+1=1+1+1+1+1 a=3
...
我们只需要给出一个总金额n就行,所以 (a-1)*2=n
#include<stdio.h>
int main(){
int n;
scanf("%d",&n);
if(n==1){
printf("1 1\n1\n");
}
else{
printf("%d 2\n",(n-1)*2);
printf("1 2\n");
}
return 0;
}
C:
首先代码参考:http://blog.youkuaiyun.com/so_so_y/article/details/78152910 感谢大佬的分享
讲解一下思路,给你n个人,每个披萨有S块,一共有两种披萨A,B。然后每一行给出 s,a,b个人需要吃的块数以及 吃A获得的愉快感和吃B披萨获得的愉快感。
要求出用最少个数的披萨获得最多的愉快感。
首先,我们每次选取 ai,bi中最大的给第i个人吃,那么当前获得的愉快感为 si*max(ai,bi) 求和,并且每次存贮 max(ai,bi)-min(ai,bi), si 存进vector 数组中,用pair类型
同时计算吃a,b的总块数 re1 re2
全部计算之后,对re1=a%S,re2= b%S,也就是买A,B pizza不到一个的块数,如果re1+re2>S那么不用处理直接输出,因为不论怎么调整,都会多买一个。
如果 re1+re2<=S 那么我们就要处理一下。
a1为把多的re1 块 a全部换成b减少的值
a2为把多的re2 块 b 全部换成a减少的值
然后比较这两个值的大小,取较小的那个减去。即可。
#include <iostream>
#include <map>
#include <set>
#include <string>
#include<string.h>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <queue>
#include <vector>
using namespace std;
typedef long long ll;
vector<pair<ll,ll>> vec1,vec2;
int main(){
ll N,S;
ll re1=0,re2=0,happy=0;
scanf("%I64d%I64d",&N,&S);
for(int i=0;i<N;i++){
ll s,a,b;
scanf("%I64d%I64d%I64d",&s,&a,&b);
if(a>b){
happy+=s*a;
re1=(s+re1)%S;
vec1.push_back(make_pair(a-b,s));
}else{
happy+=s*b;
re2=(s+re2)%S;
vec2.push_back(make_pair(b-a,s));
}
}
if(re1+re2>S) printf("%I64d\n",happy);
else{
sort(vec1.begin(),vec1.end());
sort(vec2.begin(),vec2.end());
ll a1=0,a2=0;
for(auto it=vec1.begin();it!=vec1.end();it++){
a1+=min(it->second,re1)*it->first;
re1-=min(it->second,re1);
}
for(auto it=vec2.begin();it!=vec2.end();it++){
a2+=min(it->second,re2)*it->first;
re2-=min(it->second,re2);
}
happy-=min(a1,a2);
printf("%I64d\n",happy);
}
return 0;
}
E:智商题
首先代码参考:http://www.cnblogs.com/onioncyc/p/7616959.html
中转站思想,建议模拟一遍代码,就好理解了,每次遇到一个值x,push(-x)两次,计算答案的时候用当前值加上队列中最大的负数,求和。
模拟一下代码的过程就理解了。
#include <iostream>
#include <map>
#include <set>
#include <string>
#include<string.h>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <queue>
#include <vector>
using namespace std;
typedef long long ll;
int main(){
int n;
priority_queue<int> q;
scanf("%d",&n);
ll ans=0;
for(int i=0;i<n;i++){
int x;
scanf("%d",&x);
q.push(-x);
q.push(-x);
ans+=x+q.top();
q.pop();
}
printf("%I64d\n",ans);
return 0;
}
还需要努力啊,都不算很难,思维锻炼不够。