CF Beta 49

A

题意:

给一个字符串\(s\),从一堆字符串中找到\(s\)作为前缀的,字典序最小的字符串,如果没有就输出\(s\)

题解:

暴力

#include<bits/stdc++.h>
using namespace std;
namespace red{
#define int long long
#define double long double
#define ls(p) (p<<1)
#define rs(p) (p<<1|1)
#define lowbit(i) ((i)&(-i))
#define mid ((l+r)>>1)
#define eps (1e-15)
    const int N=3e5+10,mod=998244353,inf=2e9;
    int n;
    int a[N];
    string s,ans;
    inline void main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);cout.tie(0);
        int T=1;
        while(T--)
        {
            cin>>s;
            int len=s.length();
            cin>>n;
            bool opt=0;
            for(int i=1;i<=n;++i)
            {
                string tmp;
                cin>>tmp;
                bool flag=1;
                for(int k=0;k<len;++k)
                {
                    if(s[k]!=tmp[k]){flag=0;break;}
                }
                if(!flag) continue;
                if(tmp<ans||!opt) opt=1,ans=tmp;
            }
            if(!opt) ans=s;
            cout<<ans<<'\n';
        }
    }
}
signed main()
{
    red::main();
    return 0;
}
/*


*/

B

题意:

给一个\(n*m\)的矩形,从中找到一个面积最大的,长宽之比在\([0.8,1.25]\)范围之内,且一条边是\(2\)的整次幂的矩形,有多少的话输出高最大的。

题解:

枚举一条边是\(2\)的多少次幂

#include<bits/stdc++.h>
using namespace std;
namespace red{
#define int long long
#define double long double
#define ls(p) (p<<1)
#define rs(p) (p<<1|1)
#define lowbit(i) ((i)&(-i))
#define mid ((l+r)>>1)
#define eps (1e-15)
    const int N=3e5+10,mod=998244353,inf=2e9;
    int n,m;
    int x,y;
    inline void main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);cout.tie(0);
        int T=1;
        while(T--)
        {
            cin>>n>>m;
            x=y=0;
            for(int a=1;a<=n;a<<=1)
            {
                int b=1.0*a*1.25;
                b=min(b,m);
                if(a*0.8>b) break;
                if(a*b>x*y||(a*b==x*y&&a>x)) x=a,y=b;
            }
            for(int b=1;b<=m;b<<=1)
            {
                int a=1.0*b*1.25;
                a=min(a,n);
                if(b*0.8>a) break;
                if(a*b>x*y||(a*b==x*y&&a>x)) x=a,y=b;
            }
            if(x==0&&y==0) x=n,y=m;
            cout<<x<<' '<<y<<'\n';
        }
    }
}
signed main()
{
    red::main();
    return 0;
}
/*


*/

C

题意:

\(1\sim n\)\(n\)个点,间隔\(1\)米,制定一条路线访问这\(n\)个点,路线上每相邻两段的距离长度都不同,起点随意。

题解:

\(1,n,2,n-1,3,n-2,……\)

#include<bits/stdc++.h>
using namespace std;
namespace red{
#define int long long
#define double long double
#define ls(p) (p<<1)
#define rs(p) (p<<1|1)
#define lowbit(i) ((i)&(-i))
#define mid ((l+r)>>1)
#define eps (1e-15)
    const int N=3e5+10,mod=998244353,inf=2e9;
    int n;
    int a[N];
    inline void main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);cout.tie(0);
        int T=1;
        while(T--)
        {
            cin>>n;
            int l=1,r=n;
            while(l<=r)
            {
                cout<<l++<<' ';
                if(l<=r) cout<<r--<<' ';
            }
        }
    }
}
signed main()
{
    red::main();
    return 0;
}
/*


*/

D

题意:

给一个\(a\)数组和把\(a\)随机打乱后的\(b\)数组,只能交换相邻两个数字,怎么把\(b\)还原成\(a\)

\(n\leq 300\)

题解:

暴力。

#include<bits/stdc++.h>
using namespace std;
namespace red{
#define int long long
#define double long double
#define ls(p) (p<<1)
#define rs(p) (p<<1|1)
#define lowbit(i) ((i)&(-i))
#define mid ((l+r)>>1)
#define eps (1e-15)
    const int N=3e5+10,mod=998244353,inf=2e9;
    int n;
    int a[N];
    int b[N];
    typedef pair<int,int> pr;
    pr st[N];
    int top;
    inline void main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);cout.tie(0);
        int T=1;
        while(T--)
        {
            cin>>n;
            for(int i=1;i<=n;++i)
            {
                cin>>a[i];
            }
            for(int i=1;i<=n;++i)
            {
                cin>>b[i];
            }
            for(int i=1;i<=n;++i)
            {
                if(a[i]==b[i]) continue;
                for(int j=i+1;j<=n;++j)
                {
                    if(b[j]==a[i])
                    {
                        for(int k=j;k>i;--k)
                        {
                            st[++top]=pr(k-1,k);
                            swap(b[k],b[k-1]);
                        }
                        break;
                    }
                }
            }
            cout<<top<<'\n';
            for(int i=1;i<=top;++i) cout<<st[i].first<<' '<<st[i].second<<'\n';
        }
    }
}
signed main()
{
    red::main();
    return 0;
}
/*
4
1 2 3 2
2 2 1 3


*/

E

题意:

给一张图,求它恰好有\(k\)个叶子节点的生成树个数。

\(n\leq 10\)

题解:

\(dp[s1][s2]\)是当前联通集合是\(s1\),叶子节点集合是\(s2\)的方案数。

考虑加入一个点,如果它连在原来的叶子节点上,原来的叶子节点就会变成非叶子。而新加入的点一定会变成叶子。

但是这样有重复,比如\(1-2-3\),我们往\(1-2\)里加\(3\)和往\(2-3\)里加\(1\)是同一种。

\(k\)个叶子就会重复计算\(k\)次。算出\(dp[s1][s2]\)后要把方案数除以\(s2\)\(1\)的个数。

#include<bits/stdc++.h>
using namespace std;
namespace red{
#define int long long
#define double long double
#define ls(p) (p<<1)
#define rs(p) (p<<1|1)
#define lowbit(i) ((i)&(-i))
#define mid ((l+r)>>1)
#define eps (1e-15)
    const int N=3e5+10,mod=998244353,inf=2e9;
    int n,m,k,ans;
    int f[11][11];
    int fac[11];
    int dp[1050][1050];
    inline void main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);cout.tie(0);
        int T=1;
        while(T--)
        {
            cin>>n>>m>>k;
            for(int i=1;i<=m;++i)
            {
                int x,y;cin>>x>>y;
                --x,--y;
                f[x][y]=f[y][x]=1;
                int tmp=(1<<x)|(1<<y);
                dp[tmp][tmp]=2;
            }
            fac[0]=1;
            for(int i=1;i<=n;++i) fac[i]=fac[i-1]*i;
            int S=(1<<n);
            for(int s1=1;s1<S;++s1)
            {
                for(int s2=s1;s2;s2=(s2-1)&s1)
                {
                    if(!dp[s1][s2]) continue;
                    int cnt=0;
                    for(int k=0;k<n;++k) if((s2>>k)&1) ++cnt;
                    dp[s1][s2]/=cnt;
                    //cout<<s1<<' '<<s2<<' '<<dp[s1][s2]<<"!!"<<endl;
                    for(int k=0;k<n;++k) if(((s1>>k)&1)==0)
                    {
                        for(int j=0;j<n;++j) if(((s1>>j)&1)&&f[k][j])
                        {
                            if((s2>>j)&1)
                            {
                                dp[s1|(1<<k)][s2^(1<<k)^(1<<j)]+=dp[s1][s2];
                            }
                            else
                            {
                                // if((s1|(1<<k))==15)
                                // {
                                //     if((s2^(1<<k))==14) cout<<s1<<' '<<s2<<' '<<dp[s1][s2]<<"!!!!!!!!!!!!!!!!!!"<<endl;
                                // }
                                dp[s1|(1<<k)][s2^(1<<k)]+=dp[s1][s2];
                            }
                        }
                    }
                }
            }
            for(int s=0;s<=S;++s)
            {
                int sum=0;
                for(int k=0;k<n;++k) if((s>>k)&1)
                {
                    ++sum;
                }
                if(sum==k) ans+=dp[S-1][s];
            }
            cout<<ans<<'\n';
        }
    }
}
signed main()
{
    red::main();
    return 0;
}
posted @ 2022-04-26 22:29  lovelyred  阅读(63)  评论(0)    收藏  举报