2018届四川省大学生程序设计大赛传送门入口:
https://www.oj.swust.edu.cn/problem
题目是2804~2814
省赛榜单:
http://www.cs.swust.edu.cn/standing/standing.html
B题(2805,beyond the boundry):
题意:题目给定四个字符串。给一些测试串,如果该子串在题目中的4个字符串中出现过(只要按次序出现就行,不在意是否连续),先记录出现的次数,再输出该子串。
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
string str[4]={"Kanbara Akihito","Kuriyama Mirai","Nase Hiroomi","Nase Mitsuki"};
bool vis[4];
int main(){
int t;
cin>>t;
while(t--){
memset(vis,0,sizeof(vis));
string s;
cin>>s;
int n=s.size();
int flag=0;
for(int i=0;i<4;i++){
int m=str[i].size();
int count=0;
for(int j=0;j<m;j++){
if(s[count]==str[i][j]){
count++;
}
if(count==n){
flag++;
vis[i]=1;
break;
}
}
}
cout<<flag<<endl;
for(int i=0;i<4;i++){
if(vis[i])
cout<<str[i]<<endl;
}
}
return 0;
}
E题(2808:Ever17):
给定一个日历,格式是月,日,年或者年,月,日。保证一定有一个格式是正确的,如果两次格式所对应的日期相同,输出该年月日,如果只有一种格式合法,也输出给年月日,否则输出两个日期相差的天数
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
string data[13]={"0","January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November","December"};
int month[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
bool check(int d,int m,int y){
if(y%4==0&&y%100!=0||y%400==0)month[2]=29;
else month[2]=28;
if(d<=month[m]&&m<=12&&d>0&&m>0)
return true;
return false;
}
int ansdata(int d,int m,int y){
if(y%4==0&&y%100!=0||y%400==0)month[2]=29;
else month[2]=28;
y--;
int res=y*365+y/4-y/100+y/400;
for(int i=1;i<m;i++){
res+=month[i];
}
res+=d;
return res;
}
int main(){
int t;
cin>>t;
while(t--){
int y0,m0,d0,y1,m1,d1;
scanf("%d/%d/%d",&m0,&d0,&y0);
y1=m0,m1=d0,d1=y0;
y0+=2000;
y1+=2000;
if(y0==y1&&m0==m1&&d0==d1){
cout<<data[m0];
printf(" %d, %d\n",d0,y0);
continue;
}
if(!check(d0,m0,y0)){
cout<<data[m1];
printf(" %d, %d\n",d1,y1);
continue;
}
if(!check(d1,m1,y1)){
cout<<data[m0];
printf("% d, %d\n",d0,y0);
continue;
}
int data0=ansdata(d0,m0,y0);
int data1=ansdata(d1,m1,y1);
cout<<abs(data0-data1)<<endl;
}
return 0;
}
H题(2811:harmony)
给两个数,求两个数相加然后加上两个数最小公倍数的值:
#include<iostream>
using namespace std;
int gcd(int a,int b){
if(b==0)return a;
return gcd(b,a%b);
}
int main(){
int t;
cin>>t;
while(t--){
int n,m;
cin>>n>>m;
cout<<n+m+gcd(n,m)<<endl;
}
return 0;
}
I题(2812 Island):
给定一棵树,和这颗树的权值,问删掉这颗顶点,求剩下的树的最大值,然后统计删掉每个顶点剩下树的最大值,求其中的最小值是多少。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define ll long long
const int maxn=2e5+10;
int n,T;
int u,v;
ll cost[maxn],ans[maxn];
bool vis[maxn];
ll M[maxn];
ll val[maxn];
struct node{
int v,next;
}e[maxn];
int p[maxn],eid;
void init(){
for(int i=0;i<n*2+10;i++){
p[i]=-1;
}
for(int i=1;i<=n;i++){
vis[i]=0;
cost[i]=0;
ans[i]=0;
M[i]=0;
val[i]=0;
}
eid=0;
}
void insert(int u,int v){
e[eid].v=v;
e[eid].next=p[u];
p[u]=eid++;
}
void dfs1(int u){
M[u]=-(1e18+10);
for(int i=p[u];i+1;i=e[i].next){
int v=e[i].v;
if(!vis[v]){
vis[v]=1;
dfs1(v);
val[u]+=val[v];
//统计该顶点和其子树顶点的权值和
M[u]=max(M[u],val[v]);
//记录该树中的最大顶点权值和
}
}
val[u]+=cost[u];
}
void dfs2(int u){
for(int i=p[u];i+1;i=e[i].next){
int v=e[i].v;
if(!vis[v]){
vis[v]=1;
dfs2(v);
}
}
ans[u]=max(M[u],val[1]-val[u]);
//ans[u]=val[1]-val[u];
}
int main(){
scanf("%d",&T);
while(T--){
ll Min=1e18+10;
scanf("%d",&n);
init();
for(int i=1;i<=n;i++){
scanf("%d",&cost[i]);
}
for(int i=0;i<n-1;i++){
scanf("%d%d",&u,&v);
insert(u,v);
insert(v,u);
}
vis[1]=1;
dfs1(1);
/*for(int i=1;i<=n;i++){
cout<<M[i]<<" ";
}cout<<endl;
for(int i=1;i<=n;i++){
cout<<val[i]<<" ";
}
cout<<endl;*/
for(int i=2;i<=n;i++){
vis[i]=0;
}
dfs2(1);
/*for(int i=1;i<=n;i++){
cout<<ans[i]<<" ";
}cout<<endl;*/
for(int i=1;i<=n;i++){
Min=min(Min,ans[i]);
}
printf("%lld\n",Min);
}
return 0;
}