周末抽点时间做了一下团体程序设计天梯赛的练习集,下面就记录L1题集中几道我认为测试数据有些坑的题目。题意就不再说了,写一下大体思路。附链接:https://www.patest.cn/contests/gplt 。
1. L1-006 连续因子
大体思路:求一个数的最长的连续因子,可以将这个数的所有因子全部记录起来,然后用sum记录相乘结果,从第一个开始,判断和下一个是否连续,是的话相乘赋给sum,不是就返回false;
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
typedef long long LL;
vector<LL> s;
bool judge(LL i,LL j,LL n){
int sum=1,k;
for(k=i;k<j;k++){
if(s[k]-s[k+1]!=-1)
return false;
else
sum*=s[k];
}
sum*=s[k];
if(!(n%sum)) //判断是否可以被n整除,只有一种情况不被n整除,就是sum比n大。
return true;
return false;
}
int main(){
LL n;
cin>>n;
/* 如果用这种写法将在最后一组超时
for(LL i=2;i*2<=n;i++)
if(n%i==0)
s.push_back(i);
s.push_back(n);
*/
for(LL i=2;i*i<=n;i++){
if(i*i==n)
s.push_back(i);
else if(n%i==0){
s.push_back(i);
s.push_back(n/i);
}
}
s.push_back(n);
sort(s.begin(),s.end());
LL len=0,add;
for(LL i=0;i<s.size();i++){
for(LL j=i;j<s.size();j++)
if(judge(i,j,n)&&len<j-i+1){
len=j-i+1;
add=i;
}
}
bool first=true;
cout<<len<<endl;
for(LL i=add;i<add+len;i++){
if(first){
cout<<s[i];
first=false;
}
else
cout<<'*'<<s[i];
}
cout<<endl;
return 0;
}
2. L1-009 N个数求和
大体思路:这道题有几个注意点
(1). 数字是长整数,可以用long long
(2). 每相邻两个数就要相加化简一次,不然会在测试点3错误
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
long long gcd(long long x,long long y){
return y==0?x:gcd(y,x%y);
}
long long lcm(long long x,long long y){
return x/gcd(x,y)*y;
}
long long zi[105],mu[105];
int main(){
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%lld/%lld",&zi[i],&mu[i]);
long long fenzi=zi[0],fenmu=mu[0];
for(int i=1;i<n;i++){ //相邻两个数就直接相加化简
long long LCM=lcm(fenmu,mu[i]);
fenzi=fenzi*(LCM/fenmu)+zi[i]*(LCM/mu[i]);
fenmu=LCM;
long long temp=gcd(abs(fenzi),fenmu);
fenzi/=temp;
fenmu/=temp;
}
long long temp=gcd(abs(fenzi),fenmu);
fenzi/=temp;
fenmu/=temp;
long long zheng=fenzi/fenmu;
if(zheng==0){
if(fenzi!=0)
printf("%lld/%lld\n",fenzi,fenmu);
else
printf("0\n");
}
else{
fenzi%=fenmu;
if(fenzi!=0)
printf("%lld %lld/%lld\n",zheng,fenzi,fenmu);
else
printf("%lld\n",zheng);
}
return 0;
}
3. L1-011 A-B
大体思路:这个直接用map<char,vector<int> > v1配合数组vis[10005]记录哪些字母不能输出。
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<stdlib.h>
#include<vector>
#include<map>
using namespace std;
#define maxn 10005
map<char,vector<int> > v1;
char s1[maxn],s2[maxn];
bool vis[maxn];
int main(){
memset(vis,true,sizeof(vis));
gets(s1);
for(int i=0;s1[i];i++)
v1[s1[i]].push_back(i);
gets(s2);
for(int i=0;s2[i];i++){
int k=v1[s2[i]].size();
for(int j=0;j<k;j++)
vis[v1[s2[i]][j]]=false;
}
for(int i=0;s1[i];i++)
if(vis[i])
printf("%c",s1[i]);
printf("\n");
return 0;
}
4. L1-020 帅到没朋友
大体思路:这道题直接用并查集,然后需要用数组vis记录哪些数十已经输出过的。
注意点:输出要有前导零。
#include<cstdio>
#include<cstring>
#include<vector>
#include<iostream>
using namespace std;
const int maxn=100000;
int fa[maxn];
int vis[maxn];
int child[maxn];
int getfa(int x){
if(x==fa[x])
return x;
return fa[x]=getfa(fa[x]);
}
void Merge(int a,int b){
int fa_a=getfa(a);
int fa_b=getfa(b);
fa[fa_a]=fa_b;
child[fa_b]+=child[fa_a];
}
int main(){
int n;int k;int T;
int id;
cin>>n;
for(int i=0;i<maxn;i++){
fa[i]=i;
child[i]=1;
}
memset(vis,0,sizeof(vis));
while(n--){
cin>>k;
cin>>T;
--k;
while(k--){
cin>>id;
Merge(T,id);
}
}
int m,t;
cin>>m;
vector<int> v;
while(m--){
cin>>t;
int fa_t=getfa(t);
if(!vis[t]){
vis[t]=1;
if(fa_t==t&&child[t]==1)
v.push_back(t);
}
}
if(v.size()){
for(int i=0;i<v.size();i++){
if(i)
printf(" %05d",v[i]);
else
printf("%05d",v[i]);
}
}
else
cout<<"No one is handsome"<<endl;
}
5. L1-025 正整数A+B
大体思路:用scanf("%s")读取第一个数,再用gets()读取第二个数,然后分别判断是否是数,且是否大于1000。
#include<stdio.h>
#include<string.h>
int main(){
char a[1000],b[1000];
bool flag1=true,flag2=true;
scanf("%s",a);
scanf(" ");
gets(b);
int len1=strlen(a);
int len2=strlen(b);
int numa=0,numb=0;
if(len1==0||len1>4)
flag1=false;
else{
for(int i=0;i<len1;i++)
if(a[i]<'0'||a[i]>'9'){
flag1=false;
break;
}
if(flag1){
for(int i=0;i<len1;i++)
numa=numa*10+a[i]-'0';
if(numa<1||numa>1000)
flag1=false;
}
}
if(len2==0||len2>4)
flag2=false;
else{
for(int i=0;i<len2;i++)
if(b[i]<'0'||a[i]>'9'){
flag2=false;
break;
}
if(flag2){
for(int i=0;i<len2;i++)
numb=numb*10+b[i]-'0';
if(numb>1000||numb<1)
flag2=false;
}
}
if(flag1&&flag2)
printf("%d + %d = %d\n",numa,numb,numa+numb);
else if(flag1&&!flag2)
printf("%d + ? = ?\n",numa);
else if(!flag1&&flag2)
printf("? + %d = ?\n",numb);
else
printf("? + ? = ?\n");
}