目录
1065 A+B and C (64bit) (20)大数溢出
1067 Sort with Swap(0, i)(25)贪心+set
1069 The Black Hole of Numbers(20)模拟
1071 Speech Patterns(25)Map的应用
1074 Reversing Linked List(25)链表
1079 Total Sales of Supply Chain(25)建树+dfs
1082 Read Number in Chinese(25)模拟
1086 Tree Traversals Again(25)树的遍历(中序先序转后序)
1090 Highest Price in Supply Chain(25)建树,dfs
1061 Dating(20)字符串处理
【题意】
给定字符串s1,s2,s3,s4,s1与s2中第一个相同的大写字母且小于等于G(因为一周只有7天),字母序号即周几,s1与s2中第二个相同的字符(可以是0-9,A-N)表示小时(0-23),s3和s4中第一个相同的字符的位置表示分钟,最后按给定格式输出即可。
【解题思路】
虽然是道水题,但是题意一定要理解清楚!!
【代码】
#include<bits/stdc++.h>
using namespace std;
const int maxn=105;
char s1[maxn],s2[maxn],s3[maxn],s4[maxn];
string week[]={"MON","TUE","WED","THU","FRI","SAT","SUN"};
int main()
{
scanf("%s %s %s %s",s1,s2,s3,s4);
int l1=strlen(s1),l2=strlen(s2),l3=strlen(s3),l4=strlen(s4);
int day,index,h,m;
for(int i=0;i<min(l1,l2);i++)
{
if(s1[i]==s2[i] && s1[i]>='A' && s1[i]<='G')
{
day=s1[i]-'A';
index=i;
break;
}
}
//printf("%d\n",day);
cout<<week[day]<<" ";
for(int i=index+1;i<min(l1,l2);i++)
{
if(s1[i]==s2[i])
{
if(isdigit(s1[i]))
{
h=s1[i]-'0';
break;
}
else if(s1[i]>='A' && s1[i]<='N')
{
h=s1[i]-'A'+10;
break;
}
}
}
for(int i=0;i<min(l3,l4);i++)
{
if(s3[i]==s4[i] && isalpha(s3[i]))
{
m=i;
break;
}
}
printf("%02d:%02d\n",h,m);
return 0;
}
1062 Talent and Virtue(25)排序
【题意】
根据圣人、君子、愚人、小人四个等级排序。
(1)V<L,T<L 不计入排序
(2)V>=H,T>=H 圣人
(3)V>H L<=T<H 君子
(4)L<=V,T<H且V>T 愚人
(5)剩余
然后根据总分从大到小排序,若总分相同根据V从大到小排序,V相同根据编号从小到大排序。
【解题思路】
水题,只要理清思路就好啦!
【代码】
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
struct People
{
int sno,virtue,talent;
int total;
}sage[maxn],noble[maxn],fool[maxn],rest[maxn];
bool cmp(People a,People b)
{
if(a.total!=b.total)return a.total>b.total;
else
{
return (a.virtue==b.virtue)?a.sno<b.sno:a.virtue>b.virtue;
}
}
int main()
{
int n,L,H,k1=0,k2=0,k3=0,k4=0;
scanf("%d%d%d",&n,&L,&H);
while(n--)
{
int sno,s1,s2;
scanf("%d%d%d",&sno,&s1,&s2);
if(s1<L || s2<L)continue;
else if(s1>=H && s2>=H)
{
sage[k1].sno=sno;
sage[k1].virtue=s1;
sage[k1].talent=s2;
sage[k1++].total=s1+s2;
}
else if(s1>=H && s2<H && s2>=L)
{
noble[k2].sno=sno;
noble[k2].virtue=s1;
noble[k2].talent=s2;
noble[k2++].total=s1+s2;
}
else if(s1<H && s1>=L && s2<H && s2>=L && s1>=s2)
{
fool[k3].sno=sno;
fool[k3].virtue=s1;
fool[k3].talent=s2;
fool[k3++].total=s1+s2;
}
else
{
rest[k4].sno=sno;
rest[k4].virtue=s1;
rest[k4].talent=s2;
rest[k4++].total=s1+s2;
}
}
sort(sage,sage+k1,cmp);
sort(noble,noble+k2,cmp);
sort(fool,fool+k3,cmp);
sort(rest,rest+k4,cmp);
printf("%d\n",k1+k2+k3+k4);
for(int i=0;i<k1;i++)
printf("%d %d %d\n",sage[i].sno,sage[i].virtue,sage[i].talent);
for(int i=0;i<k2;i++)
printf("%d %d %d\n",noble[i].sno,noble[i].virtue,noble[i].talent);
for(int i=0;i<k3;i++)
printf("%d %d %d\n",fool[i].sno,fool[i].virtue,fool[i].talent);
for(int i=0;i<k4;i++)
printf("%d %d %d\n",rest[i].sno,rest[i].virtue,rest[i].talent);
return 0;
}
1063 Set Similarity(25)set的使用
【题意】
给定两个整数集合,它们的相似度定义为:Nc/Nt*100%。其中Nc是两个集合都有的不相等整数的个数,Nt是两个集合一共有的不相等整数的个数。你的任务就是计算任意一对给定集合的相似度。
nc是两个集合的公共元素个数,nt是两个集合的所有包含的元素个数(其中元素个数表示各个元素之间互不相同)。
【解题思路】
用set存储每一组数据(因为会自动去重),然后再遍历两个所求序列,当序列a中与序列b中的元素重复时nt++,反之nc++,最后计算比例。啊我还是太嫩……虽然想到set但是没想到还能这么用!
【代码】
#include<bits/stdc++.h>
using namespace std;
const int maxn=55;
vector<set<int> >v;
int main()
{
int n,k;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
int m,x;
scanf("%d",&m);
set<int>s;
for(int j=0;j<m;j++)
{
scanf("%d",&x);
s.insert(x);
}
v.push_back(s);
}
scanf("%d",&k);
while(k--)
{
int a,b;
scanf("%d%d",&a,&b);
int nc=0,nt=v[b-1].size();
set<int>::iterator it;
for(it=v[a-1].begin();it!=v[a-1].end();it++)
{
if(v[b-1].find(*it)==v[b-1].end())//没找到
nt++;
else nc++;
}
double ans=(double)nc/nt*100;
printf("%.1f%%\n",ans);
}
return 0;
}
1065 A+B and C (64bit) (20)大数溢出
【题意】
给3个64位的整数a,b,c,判断a+b是否大于c。
【解题思路】
用long long 分3类讨论。
(1)若a>0 b<0 || a<0 b>0 那么a+b肯定在LL范围内,所以可以直接与c比较
(2)若a>0 b>0那么a+b若溢出会出现负数,如果出现负数肯定比c大,如果没有溢出可直接与c比较。
(3)若a<0 b<0那么a+b若溢出会出现非负数,如果出现非负数肯定比c小,如果没有溢出可直接与c比较。
【代码】
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
int main()
{
int n;
scanf("%d",&n);
LL a,b,c;
for(int i=1;i<=n;i++)
{
int flag=1;
scanf("%lld%lld%lld",&a,&b,&c);
LL sum=a+b;
if((a>=0 && b<=0) || (a<=0 && b>=0))
{
if(sum>c)flag=1;
else flag=0;
}
else if(a>=0 && b>=0)
{
if(sum<0)flag=1;
else
{
if(sum>c)flag=1;
else flag=0;
}
}
else if(a<=0 && b<=0)
{
if(sum>=0)flag=0;
else
{
if(sum>c)flag=1;
else flag=0;
}
}
printf("Case #%d: ",i);
if(flag)printf("true\n");
else printf("false\n");
}
return 0;
}
1067 Sort with Swap(0, i)(25)贪心+set
【题意】
给一个序列,每次只能让0和某个元素交换,问至少交换几次才能使这个序列有序。
【解题思路】
用pos数组存储每个元素对应的下标,a数组存储元素,用set存储下标与元素还没有对应的元素(不包括0),使查找更方便。
当0不在自己的位置时,将与0所在位置下标的元素交换,此时将会有1个元素归位,则在set中删除;当0在自己的位置时,随便在set中找一个元素与其交换,此时将不会有元素归位。
【代码】
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
int a[maxn],n,pos[maxn];
int main()
{
int ans=0,index;
set<int>s;
set<int>::iterator it;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
pos[a[i]]=i;
if(a[i]!=0 && a[i]!=i)
s.insert(a[i]);
}
while(s.size()>0)
{
index=pos[0];
if(index!=0)
{
int t=pos[index];
swap(a[index],a[t]);
pos[0]=t;
pos[index]=index;
s.erase(index);
}
else
{
int t=*s.begin();
swap(a[index],a[pos[t]]);
pos[0]=pos[t];
pos[t]=0;
}
ans++;
//printf("%d\n",s.size());
}
printf("%d\n",ans);
return 0;
}
1068 Find More Coins(30)01背包
【题意】
给n种金额的硬币看是否能刚好凑出m块钱,如果不能则输出No Solution,如果可以则输出最小的、满足给定面值和的硬币序列。
【解题思路】
不难想到这是个背包问题,难点在于如何输出最小的硬币序列,需要将硬币金额先从大到小排序,然后用vis[i][j]数组dp是否选取,如果选取了就令vis为true;然后进行01背包问题求解,如果最后求解的结果不是恰好等于所需要的价值的,就输出No Soultion,否则从ans[i][j]判断选取的情况,i从n到1表示从后往前看第i个物品的选取情况,j从m到0表示从容量m到0是否选取(j = j – w[i]),把选取情况压入ans数组中。
【代码】
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e4+5;
int w[maxn],dp[maxn],vis[maxn][105],ans[maxn];
bool cmp(int a,int b)
{
return a>b;}
int main()
{
int n,V;
scanf("%d%d",&n,&V);
for(int i=0;i<n;i++)
{
scanf("%d",&w[i]);
}
sort(w,w+n,cmp);
memset(vis,0,sizeof(vis));
for(int i=0;i<n;i++)
{
for(int j=V;j>=w[i];j--)
{
if(dp[j]<=dp[j-w[i]]+w[i])
{
dp[j]=dp[j-w[i]]+w[i];
vis[i][j]=1;
}
}
}
if(dp[V]!=V)
{
printf("No Solution\n");
return 0;
}
int m=V,cnt=0,i=n-1;
while(m)
{
if(vis[i][m])
{
ans[cnt++]=w[i];
m-=w[i];
}
i--;
}
printf("%d",ans[0]);
for(int i=1;i<cnt;i++)
printf(" %d",ans[i]);
printf("\n");
return 0;
}
1069 The Black Hole of Numbers(20)模拟
【题意】
将一个数的各位数从大到小排序得到一个数a,从小到大排序得到一个数b,当a-b=6147或0时操作结束,否则将相减得到的数一直循环上述操作。
【解题思路】
水题是水题,但是需要注意细节。
1.输入的数不一定是四位数。
2.因为我自己的程序关系,当输入数位6147和0这两种情况需要特判。
【代码】
#include<bits/stdc++.h>
using namespace std;
int a[4];
int main()
{
int n,num=0;
scanf("%d",&n);
if(n==0)
{
printf("0000 - 0000 = 0000\n");
return 0;
}
else if(n==6174)
{
printf("7641 - 1467 = 6174\n");
return 0;
}
while(n<1000)n=n*10;
while(n!=6174 && n!=0)
{
num=0;
while(n<1000)n=n*10;
while(n)
{
int x=n%10;
a[num++]=x;
n/=10;
}
//while(n<1000)n=n*10;
sort(a,a+num);
int sum1=0,sum2=0;
for(int i=0;i<num;i++)
sum1=sum1*10+a[i];
for(int i=num-1;i>=0;i--)
sum2=sum2*10+a[i];
n=sum2-sum1;
printf("%04d - %04d = %04d\n",sum2,sum1,n);
}
return 0;
}
1070 Mooncake(25)排序
【题意】
给n种蛋糕的库存数量以及价格,在给定需求m的情况下计算卖家的最大收益。
【解题思路】
按照价格和数量的比值从大到小排序,然后逐个取就可以了。
【代码】
#include<bits/stdc++.h>
using namespace std;
const int maxn=1005;
struct Node
{
double num;
double price;
double rate;
}a[maxn];
bool cmp(Node a,Node b)
{
return a.rate>b.rate;
}
int main()
{
int n,x;
scanf("%d%d",&n,&x);
for(int i=0;i<n;i++)
scanf("%lf",&a[i].num);
for(int i=0;i<n;i++)
{
scanf("%lf",&a[i].price);
a[i].rate=a[i].price/a[i].num;
}
sort(a,a+n,cmp);
int i=0;
double sum=0,y=x;
for(int i=0;i<n;i++)
{
if(y>=a[i].num)
{
sum+=a[i].price;
y-=a[i].num;
}
else
{
sum+=y/a[i].num*a[i].price;
break;
}
}
printf("%.2f\n",sum);
return 0;
}
1071 Speech Patterns(25)Map的应用
【题意】
统计一句话中单词数量最多的单词,如果数量相同则输出字典序最小的单词和数量,单词可由字母和数字构成。
【解题思路】
这里如果用string来存储时要用getline才能识别空格。将单词存入Map中并计数。这里需要注意:
1.当遍历到最后1个字母时后面若没有其他字符必须存入map中,所以if中要加一句i==s.length()-1
2.当a字符串的长度为0时不需要存入map,如果不特判map中会存入一个空字符串
【代码】
#include<bits/stdc++.h>
using namespace std;
int main()
{
string s,a="";
int k=0;
getline(cin,s);
map<string,int>m;
map<string,int>::iterator it;
for(int i=0;i<s.length();i++)
{
if(isalpha(s[i]) || isdigit(s[i]))
{
s[i]=tolower(s[i]);
a=a+s[i];
}
if((!isalpha(s[i]) && !isdigit(s[i])) || i==s.length()-1)
{
if(a.length()==0)continue;
m[a]++;
a="";
}
}
string s2;
int max1=-1;
for(it=m.begin();it!=m.end();it++)
{
if(it->second>max1)
{
s2=it->first;
max1=it->second;
}
}
cout<<s2<<" "<<max1;
return 0;
}
1074 Reversing Linked List(25)链表
【题意】
将一定长度的链表每k个长度的结点翻转,输出最后的链表。
【解题思路】
这题我感觉很坑……有以下几个注意点吧。
1.并不是所有的结点都是链表的结点,这个稍微想一下就明白了,不然告诉你首节点就没什么用了。
2.每k个长度的结点都要翻转,题中说假如链表为1→2→3→4→5→6,k=3翻转后:3→2→1→6→5→4,若k=4,4→3→2→1→5→6。
然后我刚开始没有看清第二条题意错了两个测试点,后来搜题解发现其实不用这么麻烦,直接用系统自带的reverse翻转即可(左闭右开),因为每个节点自身的地址和数据是不会变的,所以只需记录每个节点的地址直接翻转,它的next就是下个节点的地址。
【代码】
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e+5;
int a[maxn];
struct Node
{
int addr;
int data;
int next;
}node[maxn];
int main()
{
int address,n,k,cnt=0;
scanf("%d%d%d",&address,&n,&k);
for(int i=0;i<n;i++)
{
int x;
scanf("%d",&x);
node[x].addr=x;
scanf("%d%d",&node[x].data,&node[x].next);
}
while(address!=-1)
{
a[cnt++]=node[address].addr;
address=node[address].next;
}
int i=0;
while(k+i<=cnt)
{
reverse(a+i,a+i+k);
i=i+k;
}
for(int i=0;i<cnt;i++)
{
if(i==cnt-1)
printf("%05d %d -1\n",a[i],node[a[i]].data);
else
printf("%05d %d %05d\n",a[i],node[a[i]].data,a[i+1]);
}
}
1075 PAT Judge(25)排序
【题意】
有n个用户,k个问题,m次提交,输出有过提交且不是所有提交的题目都编译没通过的用户的PAT排名,排名根据总分从大到小,总分相同则名次相同,但顺序要继续根据题目的满分数量从大到小排,若这个也相同则根据序号从小到大。
【解题思路】
虽然题目看起来就是普通的排序,但是有很多细节。
1.如果这个用户没有提交过题目,或提交的题目都是编译没通过的,则不输出排名。
2.需要输出排名的用户,编译没通过的题分数记为0,其他记最高分,没有提交过的题记“-”。
【代码】
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e4+5;
int pro[6];
struct Node
{
int sno;
int score[6];
int sum=0,num=0;
void init()
{
for(int i=0;i<6;i++)
score[i]=-2;
}
}user[maxn],u[maxn];
bool cmp(Node a,Node b)
{
if(a.sum!=b.sum)
return a.sum>b.sum;
else
return (a.num!=b.num)?a.num>b.num:a.sno<b.sno;
}
int main()
{
int n,k,m,cnt=0;
scanf("%d%d%d",&n,&k,&m);
for(int i=0;i<k;i++)
scanf("%d",&pro[i]);
for(int i=1;i<=n;i++)
user[i].init(),user[i].sno=i;
for(int i=0;i<m;i++)
{
int x,a,b;
scanf("%d%d%d",&x,&a,&b);
if(user[x].score[a-1]<b)
{
user[x].score[a-1]=b;
if(user[x].score[a-1]==pro[a-1])
user[x].num++;
}
}
for(int i=1;i<=n;i++)
{
int flag=1;
for(int j=0;j<k;j++)
{
if(user[i].score[j]!=-1 && user[i].score[j]!=-2)
{
flag=0;
user[i].sum+=user[i].score[j];
}
}
if(!flag)
{
u[cnt].num=user[i].num;
u[cnt].sno=user[i].sno;
u[cnt].sum=user[i].sum;
for(int j=0;j<k;j++)
{
if(user[i].score[j]==-1)u[cnt].score[j]=0;
else u[cnt].score[j]=user[i].score[j];
}
cnt++;
}
}
sort(u,u+cnt,cmp);
int num=1,rank=1;
printf("%d %05d %d",rank,u[0].sno,u[0].sum);
for(int i=0;i<k;i++)
{
if(u[0].score[i]!=-2)
printf(" %d",u[0].score[i]);
else printf(" -");
}
printf("\n");
for(int i=1;i<cnt;i++)
{
if(u[i].sum==u[i-1].sum)
num++;
else
{
rank+=num;
num=1;
}
printf("%d %05d %d",rank,u[i].sno,u[i].sum);
for(int j=0;j<k;j++)
{
if(u[i].score[j]!=-2)
printf(" %d",u[i].score[j]);
else printf(" -");
}
printf("\n");
}
return 0;
}
1077 Kuchiguse(20)字符串处理
【题意】
给定N个字符串,求他们的公共后缀,如果不存在公共后缀,就输出“nai”。
【解题思路】
因为要求后缀所以从字符串的末尾开始比较,这里用了string感觉比较方便,当字符相同时则存入s中,然后不断拿s与新输入的字符串的末尾比较,如果过程中s的长度为0,说明不存在公共后缀,输出nai,反之则输出s。
【代码】
#include<bits/stdc++.h>
using namespace std;
int main()
{
int T,flag=0;
scanf("%d",&T);
string s1,s2,s="";
getchar();
getline(cin,s1);
getline(cin,s2);
int l1=s1.length()-1,l2=s2.length()-1;
for(int i=l1,j=l2;i>=0,j>=0;i--,j--)
{
if(s1[i]==s2[j])
s=s1[i]+s;
else
break;
}
T=T-2;
if(s.length()==0)flag=1;
while(T--)
{
getline(cin,s1);
if(!flag)
{
s2=s;
s="";
l1=s1.length()-1;
l2=s2.length()-1;
for(int i=l1,j=l2;i>=0,j>=0;i--,j--)
{
if(s1[i]==s2[j])
s=s1[i]+s;
else
break;
}
if(s.length()==0)flag=1;
}
}
if(flag)printf("nai\n");
else cout<<s<<endl;
return 0;
}
1078 Hashing(25)二次方探查法
【题意】
给出散列表长和要插入的元素,将这些元素按照读入的顺序插入散列表中,其中散列函数为h(key) = key % TSize,解决冲突采用只向正向增加的二次方探查法。如果题中给出的TSize不是素数,就取第一个比TSize大的素数作为TSize。
【解题思路】
只有两个注意点。
1.找素数,这里好像不用素数筛,直接m++然后判断就可以了。
2.二次方探查法,虽然从来没有听说过这个,但是还是简单滴,就是判断index = (key + step * step) % size有没有存在,如果不用这个,最后一个测试点回过不了。
【代码】
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e4+5;
int a[maxn];
int judge(int x)
{
if(x==1)return 0;
else if(x==2)return 1;
for(int i=2;i<=sqrt(x);i++)
if(x%i==0)return 0;
return 1;
}
int main()
{
int m,n;
scanf("%d%d",&m,&n);
while(!judge(m))m++;
set<int>s;
int cnt=0;
for(int i=0;i<n;i++)
{
int x,flag=0;
scanf("%d",&x);
for(int j=0;j<m;j++)
{
int t=(x+j*j)%m;
if(!s.count(t))
{
s.insert(t);
a[cnt++]=t;
flag=1;
break;
}
}
if(!flag)a[cnt++]=-1;
}
if(a[0]==-1)printf("-");
else printf("%d",a[0]);
for(int i=1;i<cnt;i++)
{
if(a[i]==-1)printf(" -");
else printf(" %d",a[i]);
}
printf("\n");
return 0;
}
1079 Total Sales of Supply Chain(25)建树+dfs
【题意】
给一棵树,在树根出货物的价格为p,然后从根结点开始每往下走一层,该层的货物价格将会在父亲结点的价格上增加r%,给出每个叶结点的货物量,求他们的价格之和。
【解题思路】
因为刚开始没读懂题目一直不知道这题目是什么鬼……这里给出样例的树。这图可能能治好你们的颈椎哈哈哈哈
采用dfs,建立结构体数组保存每一个结点的孩子结点的下标,如果没有孩子结点,就保存这个叶子结点的data(销售的量)。深度优先遍历的递归出口,即当前下标的结点没有孩子结点的时候,就把ans += data(货物量)* pow(1 + r, depth)计算货物量*价格引起的涨幅百分比。如果有孩子结点,就dfs深度优先遍历每一个孩子结点,并且在当前depth层数的基础上+1。最后输出ans * p(销售价格),即总价格。
参考柳神https://www.liuchuo.net/archives/2212
【代码】
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
double price,rate,ans=0;
struct Node
{
double data;
vector<int>child;
}v[maxn];
void dfs(int x,int l)
{
if(v[x].child.size()==0)
{
ans+=v[x].data*pow(1+rate,l);
return;
}
else
{
for(int i=0;i<v[x].child.size();i++)
dfs(v[x].child[i],l+1);
}
}
int main()
{
int n;
scanf("%d%lf%lf",&n,&price,&rate);
rate=rate/100;
for(int i=0;i<n;i++)
{
int x,y;
scanf("%d",&x);
if(x==0)
scanf("%lf",&v[i].data);
else
{
for(int j=0;j<x;j++)
{
scanf("%d",&y);
v[i].child.push_back(y);
}
}
}
dfs(0,0);
printf("%.1f\n",ans*price);
return 0;
}
1081 Rational Sum(20)分数运算
【题意】
给N个有理数(以分子/分母的形式给出),计算这N个数的总和,最后总和要以(整数 分子/分母)的形式给出。
【解题思路】
因为分子和分母的范围都是int,为了防止爆炸直接用long long即可。回归最本质的分数加法,两个分数a/b,c/d相加,分母是b和c的最小公倍数,分子是(gbs/b)*a+(gbs/d)*c。
【代码】
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
LL gcd(LL a,LL b)
{
while(b)
{
int x=a%b;
a=b;
b=x;
}
return a;
}
int main()
{
int n;
scanf("%d",&n);
LL sum1=0,sum2=0;
LL a,b,gcd1;
scanf("%lld/%lld",&a,&b);
gcd1=gcd(a,b);
sum1=a/gcd1;sum2=b/gcd1;
n--;
while(n--)
{
scanf("%lld/%lld",&a,&b);
gcd1=gcd(sum2,b);
LL gbs=sum2*b/gcd1;
sum1=(gbs/sum2)*sum1;
a=(gbs/b)*a;
sum1+=a;sum2=gbs;
LL t=gcd(sum1,sum2);
sum1/=t;sum2/=t;
}
LL r=sum1/sum2;
int flag=0;
if(r!=0)
{
printf("%lld",r);
flag=1;
}
LL x=sum1-r*sum2;
if(x!=0)
{
if(flag)printf(" ");
printf("%lld/%lld",x,sum2);
}
if(r==0 && x==0)printf("0");
printf("\n");
return 0;
}
1082 Read Number in Chinese(25)模拟
【题意】
将一个数字用中文读出。
【解题思路】
把数字分为三部分读即可,即亿为单位作为一部分,万为单位作为一部分,然后是剩下的,每一部分都按照千百十来计数,然后需要注意一些细节。
【代码】
#include<bits/stdc++.h>
using namespace std;
const int maxn=15;
string a[]={"ling","yi","er","san","si","wu","liu","qi","ba","jiu"};
int b[]={1,10,100,1000,10000,100000,1000000,10000000,100000000};
string c[]={"Ge","Shi","Bai","Qian","Wan"};
int main()
{
int n,o=0,p=0,q=0,flag=0,y,Y=0,W=0,G=0;
scanf("%d",&n);
if(n==0)
{
cout<<a[n]<<endl;
return 0;
}
else if(n<0)
{
cout<<"Fu"<<" ";
n=-n;
}
o=n/100000000;
p=(n%100000000)/10000;
q=n%10000;
if(o>0)
{
Y=1;
cout<<a[o]<<" Yi";
flag=1;
}
for(int i=0;i<2;i++)
{
if(i==0)y=p;
else y=q;
int flag2=0;
for(int j=3;j>=0;j--)
{
int x=(y/b[j])%10;
if(i==0 && !Y && !x && !W)continue;
if(i==1 && !W && !x && !G)continue;
if(x>0)
{
if(flag2==1)
{
flag==1?cout<<" "<<a[0]:cout<<a[0];
flag2=0;
}
if(j!=0)flag==1?cout<<" "<<a[x]<<" "<<c[j]:cout<<a[x]<<" "<<c[j];
else flag==1?cout<<" "<<a[x]:cout<<a[x];
flag=1;
}
else flag2=1;
W=1;G=1;
}
if(i==0 && W)cout<<" "<<c[4];
}
printf("\n");
return 0;
}
1083 List Grades(25)排序
【题意】
给n个人的名字科目和成绩,再给一个成绩的上界和下届,按降序输出在界限之内的人的名字科目,如果没有人在这个范围内则输出“NONE”。
【解题思路】
简单的排序,注意细节即可。
【代码】
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e+5;
struct Node
{
string name;
string cno;
int grade;
}student[maxn];
bool cmp(Node a,Node b)
{
return a.grade>b.grade;
}
int main()
{
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
cin>>student[i].name>>student[i].cno>>student[i].grade;
int l,r;
scanf("%d%d",&l,&r);
sort(student,student+n,cmp);
if(student[0].grade<l || student[n-1].grade>r)
printf("NONE\n");
else
{
for(int i=0;i<n;i++)
{
if(student[i].grade>=l && student[i].grade<=r)
cout<<student[i].name<<" "<<student[i].cno<<endl;
}
}
return 0;
}
1084 Broken Keyboard(20)字符串处理
【题意】
给两个字符串,字符串1为本来想打的字符串,字符串2为键盘坏了几个键后打出的字符串,求键盘坏了哪几个键,并输出大写字符。
【解题思路】
用set记录字符串2中出现的字符,然后遍历字符串1,若字符串1中的字符在set中没有出现过,就说明这个键坏了,但是要注意不能输出重复的键,所以要再用一个set记录坏了的键。
【代码】
#include<bits/stdc++.h>
using namespace std;
const int maxn=105;
char a[maxn],b[maxn];
int main()
{
scanf("%s",a);
set<char>s;
set<char>s2;
char x;
scanf("%s",b);
for(int i=0;i<strlen(b);i++)
{
if(isalpha(b[i]))
x=toupper(b[i]);
else x=b[i];
if(!s.count(x))
s.insert(x);
}
for(int i=0;i<strlen(a);i++)
{
if(isalpha(a[i]))
x=toupper(a[i]);
else x=a[i];
if(!s.count(x) && !s2.count(x))
{
s2.insert(x);
printf("%c",x);
}
}
printf("\n");
}
1085 Perfect Sequence(25)二分
【题意】
给定一个正整数数列,和正整数p,设这个数列中的最大值是M,最小值是m,如果M <= m * p,则称这个数列是完美数列。现在给定参数p和一些正整数,请你从中选择尽可能多的数构成一个完美数列。输入第一行给出两个正整数N(输入正数的个数)和p(给定的参数),第二行给出N个正整数。在一行中输出最多可以选择多少个数可以用它们组成一个完美数列。
【解题思路】
先将数组排序,然后用一下upper_bound找第一个大于最小值的元素的位置,更新最大长度。这里不能用lower_bound(),因为如果查找第一个大于等于最小值的元素的位置的话,当序列中有等于这个元素时,数组下标要-i+1,但是没有的话会返回一个大于这个元素的位置,就不需要+1了,所以还是用upper_bound()比较安全。
【代码】
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn=1e5+5;
LL a[maxn];
int main()
{
int n,p;
scanf("%d%d",&n,&p);
for(int i=0;i<n;i++)
scanf("%lld",&a[i]);
sort(a,a+n);
if(n==0)
{
printf("0\n");
return 0;
}
int maxlen=1;
for(int i=0;i<n;i++)
{
LL x=a[i]*p;
int t=upper_bound(a,a+n,x)-(a+i);
maxlen=max(t,maxlen);
}
printf("%d\n",maxlen);
return 0;
}
1086 Tree Traversals Again(25)树的遍历(中序先序转后序)
【题意】
用栈的push、pop操作给出一棵二叉树的中序遍历顺序,求这棵二叉树的后序遍历。
【解题思路】
对于push x操作:
1).第一个push肯定是根节点root。
2).根据child变量,建立父节点v与x的父子关系。
3).由于是中序遍历,所以接下来的节点必定是v的left(如果有的话),child=left,v=x;
4).然后进行push操作
对于pop操作:
1).根据中序遍历性质,可知接下来的节点必定是pop节点的右孩子(如果有的话),child=rightv,v=s.top()
2).进行pop操作。
转自http://www.cnblogs.com/chenxiwenruo/p/6388909.html
【代码】
#include<bits/stdc++.h>
using namespace std;
const int maxn=105;
const int LEFT=1,RIGHT=-1;
int flag=0;
struct Node
{
int left=-1;
int right=-1;
}node[maxn];
void post(int x)
{
if(x==-1)return;
post(node[x].left);
post(node[x].right);
if(!flag)
{
printf("%d",x);
flag=1;
}
else printf(" %d",x);
}
int main()
{
int n,root=-1,child=LEFT,v=-1;
stack<int>s;
scanf("%d",&n);
for(int i=0;i<2*n;i++)
{
char a[5];
scanf("%s",a);
if(a[1]=='u')
{
int x;
scanf("%d",&x);
if(root==-1)root=x;
else
{
if(child==LEFT)node[v].left=x;
else node[v].right=x;
}
v=x;
child=LEFT;
s.push(x);
}
else
{
child=RIGHT;
v=s.top();
s.pop();
}
}
post(root);
printf("\n");
return 0;
}
1090 Highest Price in Supply Chain(25)建树,dfs
【题意】
给一棵树,在树根处货物的价格为p,然后每往下走一层,价格增加r%,求所有叶子结点的最高价格,以及这个价格的叶子结点个数。
【解题思路】
和1079思路是一样滴~但是我不明白为什么中途就更新ans和最后算ans不一样,中途算(就是我注释的那句)会有一个测试点错误,难道是精度丢失?希望有大佬能够解答的话可以告诉我~感谢!!
【代码】
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
double price,rate,ans=0;
int cnt=0,maxlenth=0;
vector<int>v[maxn];
void dfs(int x,int l)
{
if(v[x].size()==0)
{
if(l>maxlenth)
{
maxlenth=l;
//ans=max(ans,pow(1+rate/100,l));
cnt=1;
}
else if(l==maxlenth)
cnt++;
return;
}
for(int i=0;i<v[x].size();i++)
dfs(v[x][i],l+1);
}
int main()
{
int n,root;
scanf("%d%lf%lf",&n,&price,&rate);
for(int i=0;i<n;i++)
{
int x;
scanf("%d",&x);
if(x==-1)root=i;
else
v[x].push_back(i);
}
dfs(root,0);
printf("%.2f %d\n",pow(1+rate/100,maxlenth)*price,cnt);
return 0;
}