Codeforces Round #177 (Div. 1) 题解【ABCD】

Codeforces Round #177 (Div. 1)

A. Polo the Penguin and Strings

题意

让你构造一个长度为n的串,且里面恰好包含k个不同字符,让你构造的字符串字典序最小。

题解

先abababab,然后再把k个不同字符输出,那么这样就是最少

代码

#include<bits/stdc++.h>
using namespace std;

string s;
int main()
{
    int n,k;
    scanf("%d%d",&n,&k);
    if(n>1&&k==1){
        cout<<"-1"<<endl;
        return 0;
    }
    if(k>n){
        cout<<"-1"<<endl;
        return 0;
    }
    if(k==1){
        for(int i=1;i<=n;i++)
            printf("a");
    }else{
        for(int i=0;i<n-k+2;i++){
            if(i%2==0)printf("a");
            else printf("b");
        }
        for(int i=2;i<k;i++)
            printf("%c",'a'+i);

    }
    printf("\n");
}

B. Polo the Penguin and Houses

题意

给你n个城市,你在x城市,那么下一步会走到a[x]城市。

现在你从前k个城市出发,最终都会走到1号点,从后面n-k个城市出发,不会走到1节点,问你一共有多少种方案。

题解

k很小,所以直接dfs就好了,可以先预处理一下一些没必要dfs的部分。

代码

#include<bits/stdc++.h>
using namespace std;
const int mod = 1e9+7;
int n,k,cnt=0;
int a[10],flag,vis[10];
long long ans = 0;
int dfs2(int x){
    if(x==1)return 1;
    if(vis[x])return 0;
    vis[x]=1;
    dfs2(a[x]);
}
void check()
{
    flag=1;
    for(int i=2;i<=k&&flag;i++){
        memset(vis,0,sizeof(vis));
        flag&=dfs2(i);
    }
    if(flag)cnt++;
}
void dfs(int x){
    if(x==k+1){
        check();
        return;
    }
    for(int i=1;i<=k;i++)
        a[x]=i,dfs(x+1);
}
int main()
{
    scanf("%d%d",&n,&k);
    ans=k;
    for(int i=0;i<n-k;i++)
        ans=(ans*(n-k))%mod;
    dfs(2);
    cout<<(ans*1ll*cnt)%mod<<endl;
}

C - Polo the Penguin and XOR operation

题意

让你构造一个排列,使得sigma(i^a[i])最大

题解

手动玩一玩可以发现,实际上是可以异或互补的,所以我们把那些互补的都给补上,答案就是最大的。

代码

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6+7;
int vis[maxn],n,a[maxn],ans[maxn];

int main(){
    scanf("%d",&n);
    for(int i=n;i>=0;i--){
        if(vis[i])continue;
        int tmp=i,len=0;
        while(tmp){
            tmp/=2;
            len++;
        }
        int Up=(1<<len)-1;
        int x2=Up^i;
        ans[i]=x2;
        ans[x2]=i;
        vis[i]=vis[x2]=1;
    }
    long long Ans = 0;
    for(int i=0;i<=n;i++)
        Ans+=i^ans[i];
    cout<<Ans<<endl;
    for(int i=0;i<=n;i++)
        cout<<ans[i]<<" ";
    cout<<endl;
}

288D - Polo the Penguin and Trees

题意

给你一棵树,问你有多少对不相交路径

题解

反过来做,然后容斥搞一搞,减去相交的对数。

分为子树外和子树内,都扣一扣就好了

代码

#include<bits/stdc++.h>
using namespace std;
const int maxn = 8e4+6;
int n;
long long s[maxn];
long long ans = 0;
vector<int> E[maxn];
void dfs(int x,int f){
    s[x]=1;
    long long tmp = 0;
    for(int i=0;i<E[x].size();i++){
        int v=E[x][i];
        if(v==f)continue;
        dfs(v,x);
        tmp+=1ll*s[x]*s[v];
        s[x]+=s[v];
    }
    ans-=1ll*tmp*(tmp+2LL*s[x]*(n-s[x]));
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<n;i++){
        int a,b;
        scanf("%d%d",&a,&b);
        E[a].push_back(b);
        E[b].push_back(a);
    }
    ans=1ll*n*(n-1LL)/2LL*(n*(n-1LL)/2LL);
    dfs(1,0);
    cout<<ans<<endl;
}
posted @ 2016-12-05 11:30  qscqesze  阅读(356)  评论(0编辑  收藏  举报