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;
}