第1题
部落的战舰可以被描述为一根弦ss它只包含“0”和“1”,表示小型战舰和大型战舰。Jaina可以对琴弦进行一些魔术表演。在一个魔法中,她选择一个具有奇数长度的任意间隔并将其反转。Jaina可以随心所欲地表演这种魔法。Jaina希望小型战舰在前线,因为它们更容易被摧毁。她向你寻求帮助,你需要告诉她她能得到的最小的字典。
就是字符串翻转问题,不过要求只可以翻转奇数个,并且求最小字典数。因为选择的是奇数长度,所以每个 01 的奇偶性是不变的,最小就是奇数和偶数位置的 1 分别移动到最后面。借助这个特点很快就可以做出来。
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+7;
void solve(){
char s[N];
int ans[N];
scanf("%s",s);
int len=strlen(s);
int j0=0,j1=0,o0=0,o1=0;
for(int i=1;i<=len;i++){
if(i%2==1&&s[i-1]=='0')j0++;
else if(i%2==1&&s[i-1]=='1')j1++;
else if(i%2==0&&s[i-1]=='0')o0++;
else if(i%2==0&&s[i-1]=='1')o1++;
}
int j=1;
while(j0--){
ans[j]=0;
j+=2;
}
while(j1--){
ans[j]=1;
j+=2;
}
j=2;
while(o0--){
ans[j]=0;
j+=2;
}
while(o1--){
ans[j]=1;
j+=2;
}
for(int i=1;i<=len;i++)printf("%d",ans[i]);
printf("\n");
}
int main(){
int t;
cin>>t;
while(t--)solve();
}
第4题
Kael'thas有一个魔方,其中包含2D平面上的所有点,其坐标为整数[0,n].他可以在飞机上画几条直线。每条线将覆盖其上的所有点。请注意,这些线没有端点,并且在两个方向上都延伸到无穷大。还有一个特殊的规则:他不能画一条覆盖点的线。(0,0)因为他的宝座在(0,0)他需要绘制的最小线数是多少,以便这些线将覆盖魔方的所有点,除了(0,0)?
签到题,画个图直接过,答案就是2*n。
#include<bits/stdc++.h>
using namespace std;
int main()
{
int t;
cin>>t;
while(t--){
int n;
cin>>n;
cout<<2*n<<endl;
}
}
第11题
瓦里安·瑞恩在战斗中获得了一块长方形的黄金,长度nn和宽度mm.现在他想在黄金上画一些线,这样以后他就可以沿着这条线切割黄金。他画的线条应满足以下要求:
- 线的端点应该在金的边界上。
- 这些线应至少平行于金的一个边界。
- 沿着所有线条切割后,每块金子都是一个长度和宽度为整数的矩形。
- 沿着所有线条切割后,每块黄金的面积至少应为kk.
- 两条线不应共享一个以上的共同点。
瓦里安·雷恩(Varian Wrynn)希望以一种最大化他绘制的线条的方式切割黄金。作为联盟的最高国王,他当然没有时间这样做。所以他找到了你!请帮他切金子!
就是求最多的刀数,明显保障长边取最大值,然后再补充另外一边。面积要大于等于k,所以尽量在同一方向上切是最优解,在另一边相切就会产生更多的小金块,面积就会更小。
#include<bits/stdc++.h>
using namespace std;
int n,m,k,t,p,ansn,ansm,ans,ln,lm;
long long int s;
int main()
{
scanf("%d",&t);
for (int i=1;i<=t;i++){
scanf("%d%d%d",&n,&m,&k);
for(int j=1;j<=n;j++){
if (j*m>=k){
ansn=floor(n/j)-1;
ln=j;
break;
}
}
//cout<<ansn;
for (int j=1;j<=m;j++){
if ((floor(m/(j+1))*ln) >= k)
continue;
else
{
ansn=ansn+j-1;
break;
}
}
// cout<<ansn<<endl;
for(int j=1;j<=m;j++){
if (j*n>=k){
ansm=floor(m/j)-1;
lm=j;
break;
}
}
for (int j=1;j<=n;j++){
if (floor(n/(j+1))*lm>=k)
continue;
else
{
ansm=ansm+j-1;
break;
}
}
cout<<max(ansn,ansm)<<endl;
}
return 0;
}
补题时间
第8题
无向图的解离集是一组顶点,如果我们只保留这些顶点之间的边,则集合中的每个顶点最多连接到一条边。解离集的大小由顶点集的大小定义。图的最大解离集由具有最大大小的图的解离集定义。西尔瓦纳斯有一个连接的无向图,该图具有以下nn顶点和n - 1边,她想找到图的最大解离集的大小。但既然她刚刚成为部落的战将,她就忙得无法解决问题。请帮助她这样做。
这道题目解离集的概念让我们思考了好久,搞明白之后也还是wa。看题解用树形dp写可以大致明白,但自己写出来还是比较难。这边是其他大佬的代码。
#include <bits/stdc++.h>
using namespace std;
#define LL long long
void solve(){
LL n;
cin >> n;
vector < vector<LL> > e(n + 1);
for (int i = 0; i < n - 1; i ++ ){
LL u, v;
cin >> u >> v;
e[u].push_back(v);
e[v].push_back(u);
}
vector < array<LL, 3> > dp(n + 1);
LL ans = 0;
function<void(LL, LL)> dfs = [&](LL u, LL fa){
dp[u][0] = 0; //不选
dp[u][1] = 1; //起点
dp[u][2] = 0; //终点
LL sum0 = 0, sum1 = 0;
for (auto v : e[u]){
if (v == fa) continue;
dfs(v, u);
sum0 += max(dp[v][0], max(dp[v][1], dp[v][2]));
sum1 += dp[v][0];
}
dp[u][0] = max(dp[u][0], sum0); //不选 u 的话,所有相连的节点不论什么状态都可以
dp[u][1] = max(dp[u][1], sum1 + 1); //选了 u 作为起点,那么所有相连的节点都不能选
for (auto v : e[u]){ //找最大的方案
if (v == fa) continue;
dp[u][2] = max(dp[u][2], sum1 - dp[v][0] + dp[v][1] + 1); //选 u 作为终点,那么要找一个起点
}
for (int i = 0; i < 3; i ++ )
ans = max(ans, dp[u][i]);
};
dfs(1, 0);
cout << ans << "\n";
}
int main(){
ios::sync_with_stdio(false);cin.tie(0);
int size(512<<20);
__asm__ ( "movq %0, %%rsp\n"::"r"((char*)malloc(size)+size));
LL T = 1;
cin >> T;
while(T -- ){
solve();
}
exit(0);
}