【CQ18阶梯赛第二场】题解

【A-H国的身份证号码I】

用N个for语句可以搞定,但是写起来不方便,所以搜索。

dfs(w,num,p)表示搜索完前w位,前面x组成的数位num,最后以为为p。

如果搜索到第N位,则表示num满足条件。

最后把所有满足条件的a[]排序后输出。

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<memory>
using namespace std;
long long a[5000000],n,k,cnt;
void dfs(int w,long long num,int p)
{
     if(w==n) {
            a[++cnt]=num;return ;
     }    
     for(int i=0;i<=k;i++){
            if(p*i<=k)
            dfs(w+1,num*10+i,i);
     }
}int main()
{
    scanf("%d%d",&n,&k);
    for(int i=1;i<=k;i++){
        dfs(1,i,i);
    }
    sort(a+1,a+cnt+1);
    for(int i=1;i<=cnt;i++)
    printf("%d
",a[i]);
    return 0;
}

【B-偶像的条件】

三个班级,肯定是每个班级选的要接近才行,所以先排序,然后枚举最矮的,然后找第二,接着找第三。

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn=100010;
int a[4][maxn];
int ans=1000000000,t1,t2,t3,tmp;
void _do(int x,int y){//x最小,y第二 
    for(int i=1;i<=a[x][0];i++) {
        t1=a[x][i];
        int pos=lower_bound(a[y]+1,a[y]+1+a[y][0],t1)-a[y];    
        t2=a[y][pos];
        pos=lower_bound(a[6-x-y]+1,a[6-x-y]+1+a[6-x-y][0],t2)-a[6-x-y];
        t3=a[6-x-y][pos];    
        if(t1!=0&&t2!=0&&t3!=0) {
            tmp=2*(t3-t1);
            if(tmp<ans) ans=tmp;
        }
    }
}
int main()
{
    int n,m,q,i,j,L;
    scanf("%d%d%d",&n,&m,&L);
    a[1][0]=n;a[2][0]=m;a[3][0]=L;
    for(i=1;i<=n;i++) scanf("%d",&a[1][i]);
    for(i=1;i<=m;i++) scanf("%d",&a[2][i]);
    for(i=1;i<=L;i++) scanf("%d",&a[3][i]);
    sort(a[1]+1,a[1]+1+n);
    sort(a[2]+1,a[2]+1+m);
    sort(a[3]+1,a[3]+1+L);
    _do(1,2);
    _do(1,3);
    _do(2,3);
    _do(2,1);
    _do(3,1);
    _do(3,2);
    printf("%d
",ans);
}

【C-数组去重】

从前往后,如果一个数不和前面的一样,则输出。

#include<cstdio>
#include<cstdlib>
#include<iostream>
using namespace std;
int main()
{
    int n,pre,t,num;
    while(scanf("%d",&n)){
        if(n==-1) return 0;
        num=0;
        pre=-123123;
        while(n--){
            scanf("%d",&t);
            if(t!=pre) {
                if(num) printf(" ");
                printf("%d",t);
                num++; 
            }
            pre=t;
        }
        printf("
");
    }
    return 0;
}

【D-分数调查】

并查集,我们先设所有人的成绩未知,如果两个人的相对成绩知道,则把二人分到同一个集合。

所以如果两个人在同一个集合,那么就可以他们的相对成绩。

相反,如果两个人不在同一个集合,那么他们的相对成绩是错误的。

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<string>
#include<memory>
using namespace std;
const int maxn=200010;
int Laxt[maxn],Next[maxn],To[maxn],V[maxn],cnt=0;
int fa[maxn],scr[maxn];//fa是分组,score代表相对分数。
void _add(int u,int v,int s){
    Next[++cnt]=Laxt[u];
    Laxt[u]=cnt;
    To[cnt]=v;
    V[cnt]=s;
}
void _dfs(int u){
    for(int i=Laxt[u];i;i=Next[i]){
        if(!fa[To[i]]){
            fa[To[i]]=fa[u];
            scr[To[i]]=scr[u]-V[i];
            _dfs(To[i]);
        }
    }
}
int main()
{
    int n,m,q,i,x,y,s;
     scanf("%d%d%d",&n,&m,&q);
     for(i=1;i<=m;i++){
            scanf("%d%d%d",&x,&y,&s);
            _add(x,y,s);
            _add(y,x,-s);
     }
     for(i=1;i<=n;i++) 
     if(!fa[i]){
            fa[i]=i;
            _dfs(i);
     }
     for(i=1;i<=q;i++){
            scanf("%d%d",&x,&y);
            if(fa[x]!=fa[y]) printf("-1
");
            else printf("%d
",scr[x]-scr[y]);
     }
     return 0;
}
原文地址:https://www.cnblogs.com/hua-dong/p/8459378.html