1. 程式人生 > >【CQ18階梯賽第二場】題解

【CQ18階梯賽第二場】題解

兩個人 i++ sin ios pri post 身份證號碼 spa 個數

【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\n",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\n",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("\n");
    }
    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\n");
            else printf("%d\n",scr[x]-scr[y]);
     }
     return 0;
}

【CQ18階梯賽第二場】題解