8.20 2020 Multi-University Training Contest 10题解及补题
8.20 2020 Multi-University Training Contest 10题解及补题
比赛过程
结尾场最后一场多校比赛,确实可能比较懈怠了,爆零
题解
1003 Mine Sweeper
题意
定义《扫雷》游戏的地图中每个空白格子的值为其周围八个格子内地雷的数量(即游戏内临近地雷数量的提示)
则一张地图的值S为所有空白格子的值总和
给定S,要求构造出一张长度与宽度均不超过25的地图,使其值等于S
解法
如果 \(*S* *≤* 24\),我们可以构造这样的地图:“.X.X.X· · · ”,可知当长度为 l 的时候,数字和就等于\(l -1\)。
如果 \(*S >* 24\),我们可以把 \(*S*\) 写成 \(*S* = 8*a* + 3*b*\) 的形式,其中$ a, b ≥ 0, b < 8$,那么我们可以构造类
似如下的地图:
. . . . . . . . .
.X.X.X.X.
. . . . . . . . .
.X.X . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . XX
其中包含恰好 $a $个孤立的 “X” 和 \(*b*\) 个右下角那种连续的 “X”,可知一个孤立的 “X” 可以对数字和带来 8 的贡献,而右下角那种连续的 “X” 一个可以带来 3 的贡献。
代码
#include<bits/stdc++.h>
using namespace std;
#define mod 1000000007
#define INF 0x3f3f3f3f
#define pi 3.141592654
#define pb push_back
#define fi first
#define se second
#define mp make_pair
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair <ll,ll> pii;
const int N = 2e6+5;
char s[33][33];
int main(){
int t,n;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
if(n <= 24){
printf("1 %d\n",n+1);
for(int i = 1 ; i <= n+1 ; i++)
if(i%2 == 1) printf("X");
else printf(".");
printf("\n");
}else{
printf("25 25\n");
int a=0,b=0;
int tem = n%8;
if(tem%3 == 0) a = n/8,b=tem/3;
if(tem%3 == 1) a = n/8 - 1 ,b = tem/3 + 3;///25,28,31
if(tem%3 == 2) a = n/8 - 2 ,b = tem/3 + 6;///26,29
for(int i = 1 ; i <= 24; i ++){
for(int j = 1 ; j <= 25 ; j++){
if(i%2 == 1) printf(".");
else if(j%2 == 0 && a>0) {printf("X");a--;}
else printf(".");
}
printf("\n");
}
for(int i = 1 ; i <= 25 ; b--,i++)
if(b>0) printf("X");
else printf(".");
printf("\n");
}
}
return 0;
}
1004 Permutation Counting
题意
对于任一种\(N\)的排列\(A\),定义它的\(E\)值为序列中满足\(A[i]>i\)的数的个数。给定\(N\)和\(K(K<=N<=1000)\),问\(N\)的排列中\(E\)值为\(K\)的个数。
解法
简单DP。\(dp[i] [j]\)表示\(i\)个数的排列中\(E\)值为\(j\)的个数。假设现在已有一个\(E\)值为\(j\)的\(i\)的排列,对于新加入的一个数\(i+1\),将其加入排列的方法有三:1)把它放最后,加入后\(E\)值不变 2)把它和一个满足\(A[k]>k\)的数交换,交换后\(E\)值不变 3)把它和一个不满足\(A[k]>k\)的数交换,交换后\(E\)值\(+1\) 根据这三种方法得到转移方程\(dp[i] [j] = dp[i - 1] [j] + dp[i - 1] [j] * j + dp[i - 1] [j - 1] * (i - j)\);
代码
#include<stdio.h>
#include<iostream>
using namespace std;
const int MAXN=1001;
long long dp[MAXN][MAXN];
const long long MOD=1000000007;
int main()
{
int n,k;
int i,j;
for(i=1;i<=1000;i++)
{
dp[i][0]=1;
for(j=1;j<i;j++)
dp[i][j]=(dp[i-1][j]+dp[i-1][j]*j+dp[i-1][j-1]*(i-j))%MOD;
}
while(scanf("%d%d",&n,&k)!=EOF)
printf("%I64d\n",dp[n][k]);
return 0;
}
1010 Tic-Tac-Toe-Nim
题意
在一个3*3的矩阵给九堆石头,A和B每次取正整数块石头,谁先使成矩阵出现一行或一列的空堆谁就赢了,斜着的不算。第一轮必须拿走整个的一堆石头。问赢的方案数
解法
第一轮如果AB取走同行同列的那么B必输,肯定是取走两堆不同行不同列的石头。则剩下七堆石头中有一堆与前面不同行不同列。那么谁先取到其余六堆都只剩一个且第七堆石头剩0个谁就赢了。就变成简单的nim博弈
代码
#include<bits/stdc++.h>
using namespace std;
int main(){
int a[4][4],n,t;
scanf("%d",&t);
while(t--){
for(int i = 1 ; i <= 3; i++)
for(int j = 1 ; j<=3 ; j++)
scanf("%d",&a[i][j]);
int sum = 0;
for(int i = 1 ; i <= 3 ; i++)
for(int j = 1 ; j <= 3 ; j++){
int flag = 1;
for(int ii = 1 ; ii <= 3 ; ii++){
for(int jj = 1 ; jj <=3 ; jj++){
if(ii == i || jj == j) continue;
int x = 0;
for(int k = 1 ; k <= 3 ;k++)
for(int l = 1 ; l <= 3 ; l++){
if((k==i&&l==j)||(k==ii&&l==jj)) continue;
if(k==i || l==j || k== ii || l == jj)
x ^= (a[k][l]-1);
else x ^= a[k][l];
}
if(x == 0){
flag = 0;
break;
}
}
if(!flag) break;
}
sum += flag;
}
printf("%d\n",sum);
}
}
1011 Task Scheduler
题意
有\(n\)个任务,\(m\)个工人,其中\(k\)个工人不能用,每个任务需要\(a_i\)个工人,且必须是可用的工人,每次任务随机选\(a_i\)个工人,如果有不可用的工人,则会重新进行选择,输出你安排任务的选择顺序,使得选择的期望最小。包装\(m-k\)个工人可以完成\(n\)个任务。
解法
对输入进行下标排序
代码
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
struct aaa{
int val;
int num;
};
bool cmp(aaa a,aaa b)
{
if(a.val!=b.val)
return a.val>b.val;
else
return a.num<b.num;
}
aaa a[10005];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n,m,k;
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i].val);
a[i].num=i;
}
if(k!=0)
sort(a+1,a+n+1,cmp);
for(int i=1;i<=n;i++)
{
if(i!=n)
printf("%d ",a[i].num);
else
printf("%d",a[i].num);
}
printf("\n");
}
return 0;
}

浙公网安备 33010602011771号