HPU2017-2016级暑期集训练习赛 【题解】

时间:2022-08-27 13:50:28

赛后分析,前半段心不静,心态有点乱,导致简单题一直wa。后半段才逐渐调整回来。 再一次感觉到心态很重要【ps 没事别看rank】

A 题 利息计算
分析, 题目信息好乱,但是看过的人很多,就想了肯定很简单,就按照最简单的写了。(其实题目把公式都说了,带公式就可以了)
代码

#include<cstdio>
#include<algorithm>
#include<math.h>
#include<queue>
#include<map>
#define LL long long
using namespace std;
const int MAXN =1000000+100;
const int MAXM= 1e6;

int main(){
int t;scanf("%d",&t);
int y,q;
double e,f,g;
while(t--){
scanf("%d%d%lf%lf%lf",&y,&q,&e,&f,&g);
double m1=y*(1+e/100*q/365);
m1=m1*(1+g/100);
double m2=y*(1+f/100*(q+365)/365);
printf("%.1lf\n%.1lf\n",m1,m2);
}
return 0;
}

B Picture
分析,没什么好说的,就是模拟,。
代码

#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<queue>
#define LL long long
using namespace std;
const int MAXN =1e5;
const int MAXM= 1e6;
int main(){

int n,m;
while(~scanf("%d%d",&n,&m)){//注意这里是n为列,m为行
for(int j=1;j<=m+2;j++){
for(int i=1;i<=n+2;i++){
if(i==1&&j==1) putchar('+');
else if(i==n+2&&j==1) putchar('+');
else if(i==1&&j==m+2) putchar('+');
else if(i==n+2&&j==m+2) putchar('+');
else if(j==1||j==m+2) putchar('-');
else if(i==1||i==n+2) putchar('|');
else putchar(' ');
}
putchar('\n');
}
putchar('\n');
}
return 0;
}

C - ZOJ
分析,同样是模拟,要分清楚各种情况,分别讨论就行。【细心就可以,我就是不细心wa一次】
代码

#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<queue>
#define LL long long
using namespace std;
const int MAXN =1e5;
const int MAXM= 1e6;
char s[MAXN];
int main(){

while(scanf("%s",s)&&s[0]!='E'){
int z=0;int o=0;int j=0;
for(int i=0;s[i];i++){
if(s[i]=='Z') z++;
if(s[i]=='O') o++;
if(s[i]=='J') j++;
}

int cnt=min(min(z,o),j);
z-=cnt;o-=cnt;j-=cnt;
while(cnt--) printf("ZOJ");

if(z==0){
int k=min(o,j);
o-=k;j-=k;
while(k--) printf("OJ");
while(o--) printf("O");
while(j--) printf("J");
}else if(o==0){
int k=min(z,j);
z-=k;j-=k;
while(k--) printf("ZJ");
while(z--) printf("Z");
while(j--) printf("J");
}else if(j==0){
int k=min(z,o);
z-=k;o-=k;
while(k--) printf("ZO");
while(z--) printf("Z");
while(o--) printf("O");
}
putchar('\n');
}
return 0;
}

D - 18岁生日
分析, 就是弄清楚闰年2月是29,这一个就可以了,然后就分开一步步算就可以了。

#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<queue>
#define LL long long
using namespace std;
const int MAXN =1e5;
const int MAXM= 1e6;
int mon[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};

bool pan(int i){
return i%4==0&&i%100!=0||i%400==0;
}
int main(){
int t;scanf("%d",&t);
while(t--){
int y,m,d;
scanf("%d-%d-%d",&y,&m,&d);
if(m==2&&d==29) {if(!pan(y+18)) puts("-1");}//出生在2月29的人只能18岁的时候还是闰年才可以。
else{
int cnt=0; // 之后分三部分

if(pan(y)) mon[2]=29;else mon[2]=28; //出生当年
cnt+=mon[m]-d;
for(int i=m+1;i<13;i++)
cnt+=mon[i];

for(int i=y+1;i<y+18;i++) //出生后一年到17岁那年
if(pan(i)) cnt+=366;else cnt+=365;

if(pan(y+18)) mon[2]=29;else mon[2]=28;// 18岁那年
for(int i=1;i<m;i++)
cnt+=mon[i];

printf("%d\n",cnt+d);
}
}
return 0;
}

E - 统计元音
水题,(心态最乱的时候,这道题居然wa了三次,吐血)
代码

#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<queue>
#define LL long long
using namespace std;
const int MAXN =1e5;
const int MAXM= 1e6;
char s[MAXN];
int main(){
int t ;
scanf("%d",&t);
getchar();//吸收回车
for(int k=1;k<=t;k++){
int a,e,i,o,u;
a=e=i=o=u=0;
gets(s);
for(int j=0;s[j];j++){
if(s[j]=='a') a++;
if(s[j]=='e') e++;
if(s[j]=='i') i++;
if(s[j]=='o') o++;
if(s[j]=='u') u++;
}
printf("a:%d\n",a);
printf("e:%d\n",e);
printf("i:%d\n",i);
printf("o:%d\n",o);
printf("u:%d\n",u);
if(k!=t) printf("\n");
}
return 0;
}

F - N!Again
同余定理的简单应用和找规律。我记得原题的N范围非常非常大 。
代码

#include<cstdio>
#include<algorithm>
#include<math.h>
#include<queue>
#define LL long long
using namespace std;
const int MAXN =1e5;
const int MAXM= 1e6;
const int mod =2009;
int main(){
LL n;
while(~scanf("%lld",&n)){
LL ans=1;
if(n<=50) //当n为41 的时候就已经全是0了,因为之前有
//个数z整除了2009 ,所以之后的数字都是这个z的倍数,故之后的数字都可以整除。
for(LL i=1;i<=n;i++)
ans=(ans%mod*i%mod)%mod;
else ans=0;

printf("%lld\n",ans);
}
return 0;
}

G - 进制转换
数学题,
代码

#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
#include<cstring>
#include<iostream>
#define LL long long
using namespace std;
const int MAXN =1e5;
const int MAXM= 1e6;
int main(){
int n;int r;
while(scanf("%d%d",&n,&r)!=EOF){
int f=1; if(n<0) f=-1; n=abs(n);
string s="";
while(n){
int k=n%r;
if(k<10) s+=k+'0';
else s+=k+'A'-10;
n/=r;
}
if(f==-1)putchar('-') ;
reverse(s.begin(),s.end());
cout<<s<<endl;
}
return 0;
}

H - 整数解
暴力解,m*n才+-10000。说明m n不大 ,可以枚举
代码

#include<cstdio>
#include<algorithm>
#include<math.h>
#include<queue>
#define LL long long
using namespace std;
const int MAXN =1e5;
const int MAXM= 1e6;

int main(){
int n,m;
while(scanf("%d%d",&n,&m)&&(n||m)){
int i,j;
for(i=-10000;i<=10000;i++)
if((n-i)*i==m) break;
if(i==10000+1) puts("No");
else puts("Yes");
}
return 0;
}

I - 所爱图书
随便一个STL(map,set)都可以用。
代码

#include<cstdio>
#include<algorithm>
#include<math.h>
#include<queue>
#include<map>
#define LL long long
using namespace std;
const int MAXN =1e5;
const int MAXM= 1e6;
map<int,int>mp; // 我用的map,来标记一个数 是不是出现过,其实用一个数组也可以。
int arr[MAXN];
bool cmp(int a,int b){
return a>b;
}
int main(){
int n;scanf("%d",&n);
int ge=0;
for(int i=0;i<n;i++){
int a;scanf("%d",&a);
if(!mp[a]) {
arr[ge++]=a;
mp[a]=1;
}
}
sort(arr,arr+ge,cmp);
int have=0;// 控制空格
for(int i=0;i<ge;i++){
if(have++) putchar(' ');
printf("%d",arr[i]);
}
return 0;
}

J - 美素数
感觉都 这道题都写烂了【ps一定要深刻理解这里用的打表,有很有用的技巧】
代码

#include<cstdio>
#include<algorithm>
#include<math.h>
#include<queue>
#include<map>
#define LL long long
using namespace std;
const int MAXN =1000000+100;
const int MAXM= 1e6;
bool su[MAXN]={1,1,0};
void dabiao(){ //素筛
for(int i=2;i*i<MAXN;i++)
if(!su[i])
for(int j=i*i;j<MAXN;j+=i)
su[j]=1;
}
int getn(int x){ //得到各个位之和
int cnt=0;
while(x){
cnt+=x%10;
x/=10;
}
return cnt;
}
int arr[MAXN]={0,0,1,2};//重点
int main(){
dabiao();
for(int i=4;i<MAXN;i++){
if(!su[i]&&!su[getn(i)]) arr[i]=arr[i-1]+1;
else arr[i]=arr[i-1];
}
int t;scanf("%d",&t);
int k=1;
while(t--){
int l,r;
scanf("%d%d",&l,&r);
printf("Case #%d: %d\n",k++,arr[r]-arr[l-1]);
}
return 0;
}

K - Ohana Cleans Up
分析 靠感觉吧,就是找到相同的字符串 次数最多的就可以。
这里用map 很简单。

#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
#include<cstring>
#include<iostream>
#include<map>
#define LL long long
using namespace std;
const int MAXN =1e5;
const int MAXM= 1e6;
map<string,int>mp;
int main(){
int n;
scanf("%d",&n);
string s="";
getchar();
int cnt=-1;
for(int i=1;i<=n;i++){
cin>>s; mp[s]++;
cnt=max(mp[s],cnt);
}
printf("%d\n",cnt);
return 0;
}

L - Alice, Bob, Two Teams
分析,暴力过

#include<cstdio>
#include<algorithm>
#include<math.h>
#include<queue>
#include<map>
#define LL long long
using namespace std;
const int MAXN =5*1e5+10;
const int MAXM= 1e6;
int arr[MAXN];
char s[MAXN];
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();}
while(ch>='0'&&ch<='9') {x=x*10+ch-'0'; ch=getchar();}
return x*f; // 刚开始没想那么多,怕暴力时间不够,就特意加的输入挂
}
/*-------------------------------------*/
int main(){
int n;scanf("%d",&n);
for(int i=1;i<=n;i++)
arr[i]=read();
scanf("%s",s+1);
LL bcnt=0;//存放 初始状态时候的b的strength得个数
for(int i=1;i<=n;i++){
if(s[i]=='B') {
bcnt+=(LL)arr[i];
arr[i]=-arr[i];// 之后要翻转,如果翻到B,
//那么一定会将B化为A,肯定要减掉这个值。而A不用管,翻转过来一定会加的。
}
}
LL maxbcnt=bcnt; LL t=bcnt;
for(int i=1;i<=n;i++){ //正向暴力一遍
bcnt=bcnt+(LL)arr[i];
maxbcnt=max(bcnt,maxbcnt);
}

for(int i=n;i>=1;i--){//反向暴力一遍 取最大值就可以
t=t+(LL)arr[i];
maxbcnt=max(t,maxbcnt);
}
printf("%lld\n",maxbcnt);
return 0;
}