记 2024.4.20
P2953
[USACO09OPEN] Cow Digit Game S
题目描述
Bessie is playing a number game against Farmer John, and she wants you to help her achieve victory.
Game i starts with an integer N_i (1 <= N_i <= 1,000,000). Bessie goes first, and then the two players alternate turns. On each turn, a player can subtract either the largest digit or the smallest non-zero digit from the current number to obtain a new number. For example, from 3014 we may subtract either 1 or 4 to obtain either 3013 or 3010, respectively. The game continues until the number becomes 0, at which point the last player to have taken a turn is the winner.
Bessie and FJ play G (1 <= G <= 100) games. Determine, for each game, whether Bessie or FJ will win, assuming that both play perfectly (that is, on each turn, if the current player has a move that will guarantee his or her win, he or she will take it).
Consider a sample game where N_i = 13. Bessie goes first and takes 3, leaving 10. FJ is forced to take 1, leaving 9. Bessie takes the remainder and wins the game.
贝茜和约翰在玩一个数字游戏.贝茜需要你帮助她.
游戏一共进行了G(1≤G≤100)场.第i场游戏开始于一个正整数Ni(l≤Ni≤1,000,000).游
戏规则是这样的:双方轮流操作,将当前的数字减去一个数,这个数可以是当前数字的最大数码,也可以是最小的非0数码.比如当前的数是3014,操作者可以减去1变成3013,也可以减去4变成3010.若干次操作之后,这个数字会变成0.这时候不能再操作的一方为输家. 贝茜总是先开始操作.如果贝茜和约翰都足够聪明,执行最好的策略.请你计算最后的赢家.
比如,一场游戏开始于13.贝茜将13减去3变成10.约翰只能将10减去1变成9.贝茜再将9减去9变成0.最后贝茜赢.
输入格式
* Line 1: A single integer: G
* Lines 2..G+1: Line i+1 contains the single integer: N_i
输出格式
* Lines 1..G: Line i contains 'YES' if Bessie can win game i, and 'NO' otherwise.
样例 #1
样例输入 #1
2
9
10
样例输出 #1
YES
NO
提示
For the first game, Bessie simply takes the number 9 and wins. For the second game, Bessie must take 1 (since she cannot take 0), and then FJ can win by taking 9.
题意是数只可以减自己每个数位上的非 最大值和最小值。
f[i]=(!(f[i-minn]&&f[i-maxn])), 表示数位上非 最小值, 同理。
注意博弈论推想必胜态必败态状态之间的关系
Code
#include <iostream>
using namespace std;
const int N=1e6+10,INF=0x3f3f3f3f;
bool f[N]={0,1,1,1,1,1,1,1,1,1};
int n;
int main()
{
int tt;
cin>>tt;
for(int i=10;i<=1e6;i++)
{
int k=i,minn=INF,maxn=-INF;
while(k)
{
if(k%10!=0) minn=min(minn,k%10);
if(k%10!=0) maxn=max(maxn,k%10);
k/=10;
}
f[i]=(!(f[i-minn]&&f[i-maxn]));
}
while(tt--)
{
cin>>n;
if(f[n]) puts("YES");
else puts("NO");
}
return 0;
}
P2216
[HAOI2007] 理想的正方形
题目描述
有一个 的整数组成的矩阵,现请你从中找出一个 的正方形区域,使得该区域所有数中的最大值和最小值的差最小。
输入格式
第一行为 个整数,分别表示 的值。
第二行至第 行每行为 个非负整数,表示矩阵中相应位置上的数。每行相邻两数之间用一空格分隔。
输出格式
仅一个整数,为 矩阵中所有“ 正方形区域中的最大整数和最小整数的差值”的最小值。
样例 #1
样例输入 #1
5 4 2
1 2 5 6
0 17 16 0
16 17 2 1
2 10 2 1
1 2 2 2
样例输出 #1
1
提示
问题规模。
矩阵中的所有数都不超过 。
的数据 。
的数据 。
这一看就有单调性啊,考虑二分。
那么 CHECK 怎么写呢?
想到要维护 mid 长的区间最大值,我们想到什么?没错,正是单调队列,或换种说法,滑动窗口。
于是我们维护二维的最大最小单调队列。 做法,此题模板
Code
#include <iostream>
#include <cstring>
#define int long long
using namespace std;
const int N=510;
int a[N][N];
int colmin[N][N],colmax[N][N],rowmin[N][N],rowmax[N][N];
int n,m,k,tt,hh;
int q[N];
bool check(int x)
{
memset(colmin,0,sizeof colmin);
memset(rowmax,0,sizeof rowmax);
memset(rowmin,0,sizeof rowmin);
memset(colmax,0,sizeof colmax);
int ans=-0x3f3f3f3f;
for(int i=1;i<=n;i++)
{
tt=-1,hh=0;
for(int j=1;j<=m;j++)
{
while(tt>=hh&&q[hh]+x<=j) hh++;
while(tt>=hh&&a[i][q[tt]]<a[i][j]) tt--;
q[++tt]=j;
if(j>=x) colmax[i][j-x+1]=a[i][q[hh]];
}
}
for(int i=1;i<=n;i++)
{
tt=-1,hh=0;
for(int j=1;j<=m;j++)
{
while(tt>=hh&&q[hh]+x<=j) hh++;
while(tt>=hh&&a[i][q[tt]]>a[i][j]) tt--;
q[++tt]=j;
if(j>=x) colmin[i][j-x+1]=a[i][q[hh]];
}
}
for(int i=1;i<=m-x+1;i++)
{
tt=-1,hh=0;
for(int j=1;j<=n;j++)
{
while(tt>=hh&&q[hh]+x<=j) hh++;
while(tt>=hh&&colmax[q[tt]][i]<colmax[j][i]) tt--;
q[++tt]=j;
if(j>=x) rowmax[j-x+1][i]=colmax[q[hh]][i];
}
}
for(int i=1;i<=m-x+1;i++)
{
tt=-1,hh=0;
for(int j=1;j<=n;j++)
{
while(tt>=hh&&q[hh]+x<=j) hh++;
while(tt>=hh&&colmin[q[tt]][i]>colmin[j][i]) tt--;
q[++tt]=j;
if(j>=x) rowmin[j-x+1][i]=colmin[q[hh]][i];
}
}
for(int i=1;i<=n-x+1;i++)
for(int j=1;j<=m-x+1;j++)
ans=max(ans,rowmax[i][j]-rowmin[i][j]);
//cout<<x<<' '<<ans<<' '<<k<<endl;
return (ans>=k);
}
signed main()
{
cin>>n>>m>>k;
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) cin>>a[i][j];
int l=2,r=min(n,m);
while(l<r)
{
int mid=l+r>>1;
if(check(mid)) r=mid;
else l=mid+1;
}
if(!check(r)) {puts("-1");return 0;}
cout<<r<<endl;
return 0;
}

浙公网安备 33010602011771号