北京信息科技大学第十二届程序设计竞赛暨ACM选拔赛 【题解完成】

83 阅读5分钟
题目难度知识点
A 爱丽丝的人偶(一)构造题
B 爱丽丝的人偶(二)组合数
C 打毛玉大赛博弈论
D 贪玩的二小姐(续)模拟 贪心
E 游戏机本当下手★★思维题
F 宵暗的妖怪★★DP
G 魔界伊始★★思维,数学
H 芭芭拉冲鸭~★★树的直径
I 永远亭的小游戏★★独立期望
J 芭芭拉冲鸭~(续)★★倍增法求LCA
K 玩具销售员签到

爱丽丝的人偶(一)

image.png

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int a[N],n;
int main(void)
{
    cin>>n;
    int cnt1=1,cnt2=n;
    for(int i=1;i<=n;i+=2) a[i]=cnt1++;
    for(int i=2;i<=n;i+=2) a[i]=cnt2--;
    for(int i=1;i<=n;i++) cout<<a[i]<<" ";
    return 0;
}

爱丽丝的人偶(二)

image.png

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
const int mod=1e9+7;
typedef long long int LL;
LL a[N],b[N],k;
set<LL>st;
LL qsm(LL a,LL b,LL p)
{
    LL sum=1;
    while(b)
    {
        if(b&1) sum=sum*a%p;
        a=a*a%p;
        b>>=1;
    }
    return sum%p;
}
void solve(int n)
{
    LL sum1=1;
    for(int i=n,j=1;j<=k;j++,i--) sum1=sum1*i%mod;
    LL sum2=1;
    for(int i=1;i<=k;i++) sum2=sum2*i%mod;
    cout<<sum1*qsm(sum2,mod-2,mod)%mod<<'\n';
}
int main(void)
{
    int m; cin>>m>>k;
    for(int i=0;i<m;i++)
    {
        LL x; cin>>x;
        st.insert(x);
    }
    solve(st.size());
    return 0;
}

打毛玉大赛

image.png

#include<bits/stdc++.h>
using namespace std;
int main(void)
{
    int a,b; cin>>a>>b;
    if( (a==1&&b==2)||(a==2&&b==1)) puts("A");
    else puts("B");
    return 0;
}

贪玩的二小姐(续)

image.png

#include<bits/stdc++.h>
using namespace std;
int main(void)
{
    int n;
    string a;
    cin>>n>>a;
    int cnt1=0,cnt2=0,ans=0;
    for(int i=0;i<n;i++)
    {
        if(a[i]=='(') cnt1++;
        else cnt2++;
        if(cnt2>cnt1) cnt1++,cnt2--,ans++;
    }
    if(n&1) puts("-1");
    else cout<<ans+abs(cnt1-cnt2)/2;
    return 0;
}

游戏机本当下手

image.png

#include<bits/stdc++.h>
using namespace std;
vector<long long int>ve;
int main(void)
{
    int n,k; cin>>n>>k;
    string s; cin>>s;
    for(int i=0;i<n;i++)
    {
        int j=i;
        while((j+1<n)&&s[j+1]==s[i]) j++;
        ve.push_back({j-i+1});
        i=j;
    }
    if(k==1)
    {
        long long int ans=0;
        for(int i=0;i<ve.size();i++) ans+=(ve[i]+1)*ve[i]/2;
        cout<<ans;
    }else{
         long long int ans=0;
        for(int i=0;i<ve.size();i++) 
        {
            int l=i+k-1;
            if(l>=ve.size()) continue;
            ans+=ve[i]*ve[l];
        }
        cout<<ans;
    }
    return 0;
}

宵暗的妖怪

image.png f[i][1] 前i个,且选择了第i个

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
typedef long long int LL;
LL a[N],f[N][2],n;
int main(void)
{
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    for(int i=1;i<=n;i++)
    {
        f[i][0]=max({f[i-1][0],f[i-1][1]});
        if(i-1>=1 && i+1<=n ) f[i][1]=max(f[i][1],f[i-2][0]+a[i]);
    }
    cout<<max(f[n][0],f[n][1])<<'\n';
    return 0;
}

魔界伊始

image.png 求它们所有的最大公约数,然后看能不能整除。

#include<bits/stdc++.h>
using namespace std;
typedef long long int LL;
const int N=1e5+10;
LL a[N],n,q;
LL gcd(LL a,LL b)
{
    return b?gcd(b,a%b):a;
}
int main(void)
{
    cin>>n;
    for(int i=0;i<n;i++) cin>>a[i];
    LL ans=a[0];
    for(int i=1;i<n;i++) ans=gcd(ans,a[i]);
    cin>>q;
    while(q--)
    {
        LL x; cin>>x;
        if(x%ans==0) puts("Yes");
        else puts("No");
    }
    return 0;
}

芭芭拉冲鸭~

image.png

#include<bits/stdc++.h>
using namespace std;
const int N=1e5*4+10;
int h[N],e[N],ne[N],idx;
int p[N],d[N],n,w[N],st[N];
int find(int x)
{
    if(x!=p[x]) p[x]=find(p[x]);
    return p[x];
}
void add(int a,int b)
{
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
int bfs(int u)
{
    for(int i=0;i<=n;i++) d[i]=0x3f3f3f3f;
    d[u]=0;
    int fa=u;
    queue<int>q; q.push(u);
    while(q.size())
    {
        int u=q.front(); q.pop();
        for(int i=h[u];i!=-1;i=ne[i])
        {
            int j=e[i];
            if(d[j]==0x3f3f3f3f)
            {
                d[j]=d[u]+1;
                if(d[j]>d[fa]) fa=j;
                q.push(j);
            }
        }
    }
    return fa;
}
int main(void)
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin>>n;
    memset(h,-1,sizeof h);
    for(int i=1;i<=n;i++) p[i]=i;
    string s; cin>>s;
    for(int i=1;i<=n-1;i++)
    {
        int a,b; cin>>a>>b;
        if(s[a-1]==s[b-1]) continue;
        add(a,b),add(b,a);
        p[find(a)]=find(b);
    }
    int ans=0;
    for(int i=1;i<=n;i++)
    {
        if(st[find(i)]) continue;
        int p=bfs(i);
        p=bfs(p);
        ans=max(ans,d[p]);
        st[find(i)]++;
    }
    cout<<ans;
    return 0;
}

永远亭的小游戏

image.png

image.png

image.png

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
const int mod=1e9+7;
typedef long long int LL;
LL n,m,k,a[N],b[N],c[N];
LL sum1,sum2,sum3;
LL qsm(LL a,LL b,LL p)
{
    LL sum=1;
    while(b)
    {
        if(b&1) sum=sum*a%p;
        a=a*a%p;
        b>>=1;
    }
    return sum%p;
}
int main(void)
{
    cin>>n>>m>>k;
    for(int i=1;i<=n;i++) cin>>a[i],sum1+=a[i];
    for(int i=1;i<=m;i++) cin>>b[i],sum2+=b[i];
    for(int i=1;i<=k;i++) cin>>c[i],sum3+=c[i];
    LL sum;
    sum1=sum1%mod,sum2=sum2%mod,sum3=sum3%mod;
    sum=sum1*sum2%mod;
    sum=(sum*sum3)%mod;
    LL temp=(n*m)%mod*k%mod;
    cout<<sum*qsm(temp,mod-2,mod)%mod;
    return 0;
}

芭芭拉冲鸭~(续)

image.png

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
const int M=1e5*2+10;
int h[N],e[M],ne[M],idx;
int depth[N],f[N][17],c[N][26];//c[i][j] 表示从根到i这条链上字母j的个数
int w[N],n,m;
void add(int a,int b)
{
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void bfs(int root)
{
    memset(depth,0x3f,sizeof depth);
    depth[0]=0,depth[root]=1;
    queue<int>q; q.push(root); c[root][w[root]]++;
    while(q.size())
    {
        int u=q.front(); q.pop();
        for(int i=h[u];i!=-1;i=ne[i])
        {
            int j=e[i];
            if(depth[j]>depth[u]+1)
            {
                depth[j]=depth[u]+1;
                for(int k=0;k<26;k++)
                    c[j][k]=c[u][k];
                c[j][w[j]]++;
                f[j][0]=u;
                for(int k=1;k<=16;k++)
                    f[j][k]=f[f[j][k-1]][k-1];
                q.push(j);
            }
        }
    }
}
int lca(int a,int b)
{
    if(depth[a]<depth[b]) swap(a,b);
    for(int k=16;k>=0;k--)
        if(depth[f[a][k]]>=depth[b])
            a=f[a][k];
    if(a==b) return a;
    for(int k=16;k>=0;k--)
    {
        if(f[a][k]!=f[b][k])
        {
            a=f[a][k];
            b=f[b][k];
        }
    }
    return f[a][0];
}
int main(void)
{
    cin>>n;
    memset(h,-1,sizeof h);
    for(int i=1;i<=n-1;i++)
    {
        int a,b; cin>>a>>b;
        add(a,b),add(b,a);
    }
    for(int i=1;i<=n;i++)
    {
        char c; cin>>c;
        w[i]=c-'a';
    }
    bfs(1);
    cin>>m;
    while(m--)
    {
        int a,b; cin>>a>>b;
        int p=lca(a,b);
        int st[26]={0};
        for(int i=0;i<26;i++){
            st[i]+=c[a][i];
            st[i]+=c[b][i];
            st[i]=st[i]-2*c[p][i];//减去重复的
        }
        st[w[p]]++;
        int ans=0,flag=0;
        for(int i=0;i<26;i++)
        {
            if(st[i]%2==0) ans+=st[i];//偶数直接加
            else ans+=(st[i]-1),flag=1;//奇数加偶数个,且标记一下可以有一个奇数。
        }
        cout<<ans+flag<<'\n';
    }
    return 0;
}

玩具销售员

image.png

#include<bits/stdc++.h>
using namespace std;
int main(void)
{
    int n,m,k; cin>>n>>m>>k;
    int ans=m/2;
    if(m%2) ans++;
    if(ans<=k) puts("Yes");
    else puts("No");
}