团体程序设计天梯赛(L1选做)

周末抽点时间做了一下团体程序设计天梯赛的练习集,下面就记录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");  
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值