A - Q老师与石头剪刀布(必做)

Input
2
3
1 1 1
RPS
3
3 0 0
RPS
Output
YES
PSR
NO
解题思路
实时的进行猜拳比赛,尽力让Q老师赢,如果Q老师所有能赢的局都赢了,
就比较是否超过了n/2次
如果不超过就输出No
如果超过了,就把那些输的局,用剩下能出的石头剪刀布给填满
输出结果
代码实现
#include<iostream>
#include<cstring>
using namespace std;
int t,n;
int a,b,c;
char s[305];
bool f[305];
char v[305];
int main()
{
cin>>t;
while(t--)
{
memset(s,0,sizeof(s));
memset(f,0,sizeof(f));
memset(v,0,sizeof(v));
cin>>n;
cin>>a>>b>>c;
int win_times; //需要赢的次数
if(n%2==0)
win_times = n/2;
else
win_times = n/2 + 1;
for(int i=0;i<n;i++)
cin>>s[i];
int win=0; int flag=0;
for(int i=0;i<n;i++)
{
if(s[i]=='R' && b!=0)
{
win++;b--;f[i]=1;v[i]='P';
}
else if(s[i]=='P' && c!=0)
{
win++;c--;f[i]=1;v[i]='S';
}
else if(s[i]=='S' && a!=0)
{
win++;a--;f[i]=1;v[i]='R';
}
if(win>=win_times)
{
flag=1; break;
}
}
if(flag == 0) {
cout<<"NO"<<endl; continue;
}
else {
cout<<"YES"<<endl;
for(int i=0;i<n;i++)
{
if(f[i]) cout<<v[i];
else
{
if(a>0) { cout<<"R";a--;
}
else if(b>0){
cout<<"P"; b--;
}
else if(c>0){
cout<<"S"; c--;
}
}
}
cout<<endl;
continue;
}
}
return 0;
}
B - Q老师与十字叉(必做)

Input
9
5 5
..*..
..*..
*****
..*..
..*..
3 4
****
.*..
.*..
4 3
***
*..
*..
*..
5 5
*****
*.*.*
*****
..*.*
..***
1 4
****
5 5
.....
..*..
.***.
..*..
.....
5 3
...
.*.
.*.
***
.*.
3 3
.*.
*.*
.*.
4 4
*.**
....
*.**
*.**
Output
0
0
0
0
0
4
1
1
2
思路
暴力做法
直接遍历,把每行每列的黑格子数给记下来
再遍历一次。把每个格子当做十字架的中心,然后
计算需要填多少黑格子
然后求出最小的,或者0
代码
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 5e4+5;
const int inf=1e9;
int q,n,m;
int row[N]; //一行有多少黑
int col[N]; //一列有多少黑
int main()
{
// ios::sync_with_stdio(0);
// cin>>q;
scanf("%d",&q);
while(q--)
{
// cin>>n>>m;
scanf("%d%d",&n,&m);
char**c = new char*[n];
for(int i=0;i<n;i++)
{
c[i]=new char[m];
}
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
cin>>c[i][j];
// scanf("%c",&c[i][j]);
}
}
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
if(c[i][j]=='*') {
row[i]++;
col[j]++;
}
}
}
int min1=inf;
bool flag=0;
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
if(row[i]==m&&col[j]==n) {
// cout<<0<<endl;
printf("0\n");
flag = 1;break;
}
if(c[i][j]=='*') {
min1 = min (min1,m-row[i]+n-col[j]);
}
else if(c[i][j]=='.')
{
min1 = min (min1,m-row[i]+n-col[j]-1);
}
}
if(flag) break;
}
if(!flag)
// cout<<min1<<endl;
printf("%d\n",min1);
memset(row,0,sizeof row);
memset(col,0,sizeof col);
}
return 0;
}
C - Q老师的考验(必做)

Sample Input
10 9999
1 1 1 1 1 1 1 1 1 1
20 500
1 0 1 0 1 0 1 0 1 0
Sample Output
45
104
解题思路
矩阵快速幂 + 线性递推

我们设 F(x) = M* F(x-1)
要想得到f(x),就必须得到F(x)
例如 F(13) = M^4 * F(9)
其中F(9)的值我们已知
就转换成了矩阵快速幂求 M^4
代码实现
#include<iostream>
#include<cstring>
using namespace std;
int k,m;
bool a[14];
const int N=10;
//矩阵定义
struct Matrix{
int x[N][N];
Matrix operator*(const Matrix& t) const{
Matrix ret;
for(int i=0;i<N;i++)
{
for(int j=0;j<N;j++)
{
ret.x[i][j]=0;
for(int k=0;k<N;k++)
{
ret.x[i][j] +=x[i][k] * t.x[k][j] % m;
ret.x[i][j] %=m;
}
}
}
return ret;
}
Matrix() { memset(x,0,sizeof x);
}
Matrix(const Matrix& t){ memcpy(x,t.x,sizeof x);
}
};
//矩阵快速幂
Matrix quilck_pow(Matrix a,int x)
{
Matrix ret;
int n=0;
while(n<N)//单位矩阵
{
ret.x[n][n] = 1;
n++;
}
while(x){
if(x&1) ret = ret * a;
a=a*a;
x>>=1;
}
return ret;
}
//求f(x)
int fun(int x)
{
if(x<10) return x;
else
{
Matrix M; //初始化矩阵 M
for(int i=0;i<N;i++)
M.x[0][i]=a[i];
for(int i=1;i<N;i++)
M.x[i][i-1] = 1;
int pow=x-N+1;
Matrix res;
res=quilck_pow(M,pow);
int sum=0;
for(int i=0,j=9;i<N;j--,i++)
{
sum += (res.x[0][i] * j);
}
return sum;
}
}
int main()
{
while(cin>>k>>m)
{
memset(a,0,sizeof a);
for(int i=0;i<N;i++)
cin>>a[i];
int res=fun(k);
cout<<res%m<<endl;
}
return 0;
}
本文解析了三道算法竞赛题目,包括石头剪刀布博弈策略、十字叉填充优化及矩阵快速幂应用,涵盖博弈论、贪心算法、矩阵运算等核心概念。

469

被折叠的 条评论
为什么被折叠?



