D.The Game of Eating
思路:考虑贪心。每个人都会选择一道对于自身价值最大的菜,但考虑到其他人会帮自己提供一定的贡献,即样例二,第一个只需要点第三道菜,第二个人点第四道菜,自动帮第一个人补全了第四道价值最大的菜,所以当前人的选择可能要考虑到后续人员的影响,既然如此,我们考虑最后一个人,即最后一个进行点菜时,没有人对其选择造成影响,然后依次往前推,每个人取当前的最大价值即可。
#include <bits/stdc++.h>using namespace std;
const int N = 1e6 + 10;
typedef long long ll;
typedef pair<ll, ll> pll;
typedef array<int, 3> p3;
int mod = 51123987;
const int maxv = 4e6 + 5;int st[2005];
int a[2005][2005];
void solve()
{memset(st,0,sizeof st);int n,m,k;cin>>n>>m>>k;for(int i=1;i<=n;i++){for(int j=1;j<=m;j++) cin>>a[i][j];}int res=k%n;if(res==0) res=n;vector<int> ans;for(int i=res;i>=1;i--){int val=0;int c=0;for(int j=1;j<=m;j++){if(st[j]) continue;if(a[i][j]>val){val=a[i][j];c=j;}}st[c]=1;ans.push_back(c);if(i==1) i=n+1;k--;if(k==0) break;}sort(ans.begin(),ans.end());for(auto x: ans) cout<<x<<" ";cout<<endl;}int main()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int t;t = 1;cin >> t;while (t--){solve();}//cout<<endl;system("pause");return 0;
}
E.The Game of Eating
思路:考虑去枚举每个k,因为k最多只能到18,数据范围很小,然后按照题意去模拟即可。
#include<bits/stdc++.h>using namespace std;
const int N=1e5+5;
typedef long long ll;
typedef pair<ll,ll> pll;
int mod=998244353;
const int maxv=4e6+5;void solve()
{ ll n;cin>>n;ll x=10;for(int i=0;;i++){if(i==0) x=1;else x*=10;if(x*n>1e18) break;ll t=sqrtl(x*n);if(t*t/x==n) {cout<<t<<endl;return ;}if((t+1)*(t+1)/x==n){cout<<t+1<<endl;return; }}cout<<-1<<endl;
}int main()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int t;t=1;cin>>t;while(t--){solve();}system("pause");return 0;
}
F.Link with Chess Game
思路:官方题解给定的是二分图博弈,以后有空在去了解吧。
当n为偶数时,先手必胜,当为奇数时,和r,g,b的状态相同,当r,g,b为偶数的时候先手必胜。
#include <bits/stdc++.h>using namespace std;
const int N = 1e6 + 10;
typedef long long ll;
typedef pair<int, int> pll;
typedef array<int, 3> p3;
int mod = 1e9 + 7;
const int maxv = 4e6 + 5;void solve()
{int n,r,g,b;cin>>n>>r>>g>>b;if(n%2==0){cout<<"Alice"<<endl;return ;}else{if((r+g+b)%2==0){cout<<"Alice"<<endl;return ;}}cout<<"Bob"<<endl;}int main()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int t;t = 1;cin >> t;while (t--){solve();}system("pause");return 0;
}
G.Link with Centrally Symmetric Strings
题意:题目给定关于回文对称的新定义,然后问是否可以将给定字符串拆解成若干个回文字符串。
思路:关于回文字符串,我们可以用马拉车算法处理出每个位置上的回文半径,然后设置一个变量f 在遍历整个字符串时去记录最长的不合法的长度,若当前位置的回文半径大于不合法长度,那么直接跳到i+f处。最后变量值若为0则表示为合法字符串。
接下来来证明为什么这么做是对的:
1 若给定字符串s不嫩被拆解成若干个回文对称字符串,即存在某一些位置不是回文对称的,那么从该位置开始,变量f值会一直大于后续的所有的回文半径。因为只要出现回文半径大于f的情况,f就会被置为0,重新开始。
2 若给定字符串能够被拆解成若干个回文对称字符串,那么每当匹配到回文对称中心时,此时的位置距离前一个回文字符串的结尾距离即为p[i],而此时的回文半径长度肯定是大于f的,所以会一直匹配下去。
#include <bits/stdc++.h>using namespace std;
const int N = 1e6 + 10;
typedef long long ll;
typedef pair<int, int> pll;
typedef array<int, 3> p3;
int mod = 1e9 + 7;
const int maxv = 4e6 + 5;int z[300];
int p[N*2];void solve()
{string s;cin>>s;string a;a='#';for(int i=0;i<s.size();i++){a.push_back(s[i]);a.push_back('#');}a=" "+a;int n=a.size();for(int i=1;i<n;i++){if(z[a[i]]==a[i]) p[i]=1;else p[i]=0;}int r=0,m=0;for(int i=1;i<n;i++){if(i<r) p[i]=min(p[m*2-i],r-i+1);while(z[a[p[i]+i]]==a[i-p[i]]&&p[i]+i<n) p[i]++;if(i+p[i]-1>r){r=i+p[i]-1;m=i;}}int f=0;for(int i=1;i<n;i++){//cout<<p[i]<<" ";if(p[i]>f){i+=f;f=0;}else f++;}if(!f){cout<<"Yes"<<"\n";}else cout<<"No"<<"\n";}int main()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int t;t = 1;cin >> t;z['b']='q';z['q']='b';z['d']='p';z['p']='d';z['n']='u';z['u']='n';z['o']='o';z['s']='s';z['x']='x';z['z']='z';z['#']='#';while (t--){solve();}system("pause");return 0;
}
思考:为什么是将当前位置加上变量f,而不是直接让i加上回文半径p:考虑下述情况:
当我们将字符串的黄色部分遍历完后(保证此种情况l1的右界小于l2),此时f=0,当我们遍历到对称中心l1时,我们若直接让i加上对应的回文半径p[l1]时,会直接变为l2附近,那么后续会出现还有一半的蓝色部分不为回文字符串。若是加上对应的f,因为f的值肯定是小于对应回文半径的,所以在其回文半径内,即使半径进行减小,也为回文字符串。所以此时让i加上对应的f到蓝色字符串的开头即可。然后蓝色字符串匹配到l2出自然会结束匹配。
I.Link with Gomoku
题意:给定一个n*m的棋盘下五子棋,让构造出一个棋局为和棋。
思路:按照样例模拟即可。即放四个白子,一个黑子,下一行放四个黑子,一个百子,然后找题目要求去后续填充即可。
#include<bits/stdc++.h>using namespace std;
const int N=1e5+5;
typedef long long ll;
typedef pair<ll,ll> pll;
int mod=998244353;
const int maxv=4e6+5;void solve()
{ int n,m;cin>>n>>m;if(n%2){for(int i=1;i<=n-1;i++){if(i%2){for(int j=1;j<=m;j++){if(j%5==0) cout<<'o';else cout<<'x';}}else{for(int j=1;j<=m;j++){if(j%5==0) cout<<'x';else cout<<'o';}}cout<<endl;}for(int i=1;i<=m;i++){if(i%2) cout<<'x';else cout<<'o';}cout<<endl;}else{for(int i=1;i<=n;i++){if(i%2){for(int j=1;j<=m;j++){if(j%5==0) cout<<'o';else cout<<'x';}}else{for(int j=1;j<=m;j++){if(j%5==0) cout<<'x';else cout<<'o';}}cout<<endl;}}}int main()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int t;t=1;cin>>t;while(t--){solve();}system("pause");return 0;
}
K.Box
#include<bits/stdc++.h>using namespace std;
const int N=1e6+5;
typedef long long ll;
typedef pair<ll,ll> pll;
int mod=998244353;
const int maxv=4e6+5;ll dp[N][3];
ll a[N],b[N];void solve()
{ int n;cin>>n;vector<int> pos;for(int i=1;i<=n;i++){cin>>a[i];}pos.push_back(0);for(int i=1;i<=n;i++){cin>>b[i];if(b[i]==1) pos.push_back(i);}memset(dp,-0x3f,sizeof dp);if(pos.size()==1){cout<<0<<endl;return ;}if(pos[1]-1>0) dp[1][0]=a[pos[1]-1];if(pos[1]+1<=n) dp[1][2]=a[pos[1]+1];dp[1][1]=a[pos[1]];for(int i=2;i<pos.size();i++){for(int j=0;j<3;j++){for(int k=0;k<3;k++){if(pos[i-1]+k-1<pos[i]+j-1&&pos[i]+j-1<=n){dp[i][j]=max(dp[i][j],dp[i-1][k]+a[pos[i]+j-1]);}}}}int x=pos.size()-1;cout<<max({dp[x][0],dp[x][1],dp[x][2]})<<endl;
}int main()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int t;t=1;//cin>>t;while(t--){solve();}system("pause");return 0;
}