您的位置:首页 > 其它

COCI 2013/2014 1st round, September 28th, 2013 解题报告

2017-02-21 20:20 337 查看

TRENER

给出一堆人的英文名字(全是小写字母),若有一些字母作为首字母出现不少于5次,则输出所有符合条件的字母。

每读入一个姓名,就给该姓名首字母的次数+1。最后扫一遍所有字母作为首字母出现的次数,大于等于5的输出。

#include<bits/stdc++.h>
#define ll long long
#define inf 999999999
using namespace std;
int n,a[28];
bool flag;
int main(){
freopen("trener.in","r",stdin);
freopen("trener.out","w",stdout);
ios::sync_with_stdio(false);
cin>>n;
for(int i=1;i<=n;i++){
string tmp;
cin>>tmp;
a[tmp[0]-'a']++;
}
for(int i=0;i<26;i++){
if(a[i]>=5){
char out=i+'a';
cout<<out;
flag=1;
}
}
if(!flag)
cout<<"PREDAJA";
cout<<endl;
return 0;
}


KUŠAČ

给出一些完全相等的香肠和参会人数,香肠需要平分给所有人,至少要切几刀可以使每个人得到等量的香肠?

模拟题,将所有香肠首尾相连成一条长香肠,给每个人按顺序切一段,若切的地方刚好是连接处,则不必计数,否则答案+1。输出答案即可。

#include<bits/stdc++.h>
#define ll long long
#define inf 999999999
using namespace std;
int n,m,ans;
int main(){
freopen("kusac.in","r",stdin);
freopen("kusac.out","w",stdout);
ios::sync_with_stdio(false);
cin>>n>>m;
for(int i=0;i<=n*m;i+=n) if(i%m) ans++;
cout<<ans<<endl;
return 0;
}


RATAR

给出一个正方形中每个小方格的权值,问有多少种长方形组合,使该两个长方形权值和相等且两个长方形顶角相连。

f[i][j]表示以(i,j)为右下角的长方形的权值和。首先用求前缀和的方式求出所有的f[i][j],这样就能快速算出各个矩形的权值和。然后n^2枚举每一个点,并n^2枚举所有以该点为右下角的矩形,计算各个权值的数量。接下来n^2枚举所有以(i+1,j+1)为右上角的矩形,加上刚才算的该权值的矩形的数量。同理处理(i,j)分别为两个矩形的右下角和左上角的情况。

注意,每次枚举完一个点都要重新计数。

#include<bits/stdc++.h>
#define ll long long
#define inf 999999999
using namespace std;
const int c=2500000;
int n,f[55][55],tot,ans;
int cnt[2*c];
int cal(int x1,int y1,int x2,int y2){
return f[x2][y2]-f[x1-1][y2]-f[x2][y1-1]+f[x1-1][y1-1];
}
int main(){
freopen("ratar.in","r",stdin);
freopen("ratar.out","w",stdout);
ios::sync_with_stdio(false);
cin>>n;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
cin>>f[i][j];
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
f[i][j]+=f[i][j-1];
for(int j=1;j<=n;j++)
for(int i=1;i<=n;i++)
f[i][j]+=f[i-1][j];
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
for(int a=1;a<i;a++)
for(int b=1;b<j;b++)
cnt[cal(a,b,i-1,j-1)+c]++;
for(int a=i;a<=n;a++)
for(int b=j;b<=n;b++)
ans+=cnt[cal(i,j,a,b)+c];
for(int a=1;a<i;a++)
for(int b=1;b<j;b++)
cnt[cal(a,b,i-1,j-1)+c]--;
for(int a=i;a<=n;a++)
for(int b=1;b<j;b++)
cnt[cal(i,b,a,j-1)+c]++;
for(int a=1;a<i;a++)
for(int b=j;b<=n;b++)
ans+=cnt[cal(a,j,i-1,b)+c];
for(int a=i;a<=n;a++)
for(int b=1;b<j;b++)
cnt[cal(i,b,a,j-1)+c]--;
}
}
cout<<ans<<endl;
return 0;
}


LOPOV

给出一些物品的重量和权值,给出一些背包的容量,且每个背包最多放一件物品,求能装下的物品的权值和最大是多少。

将每个背包当做权值为-1的物品, 与其他物品一起,按照重量由小到大排序,若重量相等,则按权值由大到小排序(确保同重量的时候背包在物品后)。建立一个优先队列,遍历所有物品和背包,若权值不为-1,即该物品不为背包,则将该物品的权值加入优先队列;若权值为-1,该物品为背包,则将优先队列队首的元素取出加入答案。(这个方法跑的比标程快233)

#include<bits/stdc++.h>
#define ll long long
#define inf 999999999
using namespace std;
const int M=600005;
int n,k;
ll ans;
struct no{
int m,v;
}a[M];
priority_queue<int> q;
bool cmp(no a,no b){
return a.m!=b.m?a.m<b.m:a.v>b.v;
}
int main(){
freopen("lopov.in","r",stdin);
freopen("lopov.out","w",stdout);
ios::sync_with_stdio(false);
cin>>n>>k;
for(int i=1;i<=n;i++)
cin>>a[i].m>>a[i].v;
for(int i=1;i<=k;i++){
cin>>a[i+n].m;
a[i+n].v=-1;
}
sort(a+1,a+n+k+1,cmp);
for(int i=1;i<=n+k;i++){
if(a[i].v!=-1)
q.push(a[i].v);
else if(!q.empty()){
ans+=q.top();
q.pop();
}
}
cout<<ans<<endl;
return 0;
}


ORGANIZATOR

给出若干个俱乐部的人数,由你制定每个比赛队伍的人数,每个队伍的人必须来自同一个俱乐部,若某个俱乐部的成员不能全员参加比赛,该俱乐部便不会参加比赛。每个俱乐部的排名第一的队伍将进入比赛(若进入决赛的队伍少于2支便不算决赛)。求问最多能有多少人数进入决赛。

转化一下,其实这道题便是给出一堆数字,求找一个数,使能整除该数的数的个数(必须不小于2)*该数的值最大,输出这个最大值。

对输入的每个数进行计数,然后开始从1到2000000枚举数i,将所有是i的倍数的数的数量加和,若数量和*i大于当前答案则更新答案。

#include<bits/stdc++.h>
#define ll long long
#define inf 999999999
using namespace std;
const int M=2000005;
int n,a[M];
ll ans;
int main(){
freopen("organizator.in","r",stdin);
freopen("organizator.out","w",stdout);
ios::sync_with_stdio(false);
cin>>n;
for(int i=1;i<=n;i++){
int x;
cin>>x;
a[x]++;
}
for(int i=1;i<=2000000;i++){
int cur=0;
for(int j=i;j<=2000000;j+=i)
cur+=a[j];
if(cur>1) ans=max(ans,(ll)cur*i);
}
cout<<ans<<endl;
return 0;
}


SLASTIČAR

给出一个A串,和一些B串,开始进行匹配,匹配方法是对于逐位对比,若有某一位不同则从起始位置的下一位开始重新匹配(也就是暴力匹配),若匹配成功或匹配到A串尾依然无法匹配成功,则停止匹配。每匹配一位消耗1单位时间,分别求出匹配每个串的时间。

正在研究中,稍后奉上。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  COCI