题目顺序不分难度
K | Box |
状态dp,因为每个棋子只能移动到 i-1 到 i+1的位置,所以直接用4个状态表示棋子在哪
f[i][0] 表示前i个位置中,i-1到i+1都没有棋子
f[i][1] 表示前i个位置中,i-1有棋子
f[i][2] 表示前i个位置中,i有棋子
f[i][3] 表示前i个位置中,i+1有棋子
考虑转移
f[i][max(0,j-1)]=max(f[i][max(0,j-1)],f[i-1][j]);
因为i-1到i的位置挪动了一位,所以上面的 i 的状态1= i-1的状态0,2=1,3=2..
然后那个k循环就是因为i-1的的状态的位置因为有棋子了,不能动他,所以i只能从其他位置挪枚举挪的距离即可
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+10;
#define int long long
int a[N],b[N];
int n,m;
int f[N][4]
void solve(){
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++) cin>>b[i];
for(int i=1;i<=n;i++){
for(int j=0;j<4;j++){
f[i][max(0,j-1)]=max(f[i][max(0,j-1)],f[i-1][j]);
for(int k=j;k<4;k++){
if(k&&b[i+k-2]){
f[i][k]=max(f[i][k],f[i-1][j]+a[i]);
}
}
}
}
cout<<max({f[n][0],f[n][1],f[n][2]});
}
signed main(){
cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
int t=1;
//cin>>t;
while(t--) solve();
}
I | Link with Gomoku |
我直接分四种情况讨论了大体框架都是
XOXO
XOXO
XOXO
XOXO
OXOX
这样然后因为n*m是奇数的情况下X要比O剁,或者有奇数列和奇数行,我直接把第一行固定了,让他变成偶数
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+10,mod=998244353;
#define int long long
typedef pair<int, int> PII;
typedef long long LL;
int n,m,k;
int a[N];
int qmi(int a, int k, int p) // 求a^k mod p
{
int res = 1;
while (k)
{
if (k & 1) res = (LL)res * a;
a = (LL)a * a ;
k >>= 1;
}
return res;
}
void solve()
{
cin>>n>>m;
int now=0;
string s="xo";
char x='x';
if(m%2==0)
{
if(n%2==0)
{
for(int i=1;i<=n;i++)
{
for(int j=1,c=0;j<=m;j++,c^=1)
{
cout<<s[c];
}
now++;
cout<<"\n";
if(now==4) swap(s[0],s[1]),now=0;
}
}
else
{
for(int i=1,c=1;i<=m;i++,c^=1){
cout<<s[c];
}
cout<<"\n";
for(int i=2;i<=n;i++)
{
for(int j=1,c=0;j<=m;j++,c^=1)
{
cout<<s[c];
}
now++;
cout<<"\n";
if(now==4) swap(s[0],s[1]),now=0;
}
}
}
else
{
if(n%2==0)
{
for(int i=1;i<=n;i++)
{
for(int j=1,c=0;j<=m;j++,c^=1)
{
if(j==m){
cout<<x;
if(x=='x') x='o';
else x='x';continue;
}
cout<<s[c];
}
now++;
cout<<"\n";
if(now==4) swap(s[0],s[1]),now=0;
}
}
else
{
for(int j=1,c=1;j<=m;j++,c^=1)
{
if(j==m){
cout<<'x';continue;
}
cout<<s[c];
}
cout<<"\n";
for(int i=2;i<=n;i++)
{
for(int j=1,c=0;j<=m;j++,c^=1)
{
if(j==m){
cout<<x;
if(x=='x') x='o';
else x='x';continue;
}
cout<<s[c];
}
now++;
cout<<"\n";
if(now==4) swap(s[0],s[1]),now=0;
}
}
}
}
// 2 3 1 3 3
signed main(){
cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
int t=1;
cin>>t;
while(t--) solve();
}
我是直接枚举分母,然后二分y的
因为y越大x越大,反之一样,有单调性,所以我直接二分了
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6+10,mod=998244353;
#define int long long
typedef pair<int, int> PII;
typedef long long LL;
int n,m,k;
int a[N];
int b[N];
int qmi(int a, int k) // 求a^k mod p
{
int res = 1;
while (k)
{
if (k & 1) res = (LL)res * a ;
a = (LL)a * a ;
k >>= 1;
}
return res;
}
void solve()
{
int x;
cin>>x;
for(int i=0;i<18;i++)
{
int l=0,r=1e9;
while(l<r){
int mid=l+r+1>>1;
if(mid*mid/qmi(10,i)<=x) l=mid;
else r=mid-1;
}
if(l*l/qmi(10,i)==x){
cout<<l<<"\n";return ;
}
}
cout<<"-1\n";
}
// 2 3 1 3 3
signed main(){
cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
int t=1;
cin>>t;
while(t--) solve();
}
第一个操作是把X取反,等于-X-1
对于X来说,B操作是+1,A操作是-1
对于-X来说,B操作是-1,A操作上+1
X最后的正负只取决于[l,r]中 A的奇偶性,偶数为正,否则为反
最后答案相当于 (+-X)+C,C为上面ab操作合起来的常数,使用前缀和统计常数和和A的个数
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+10;
#define ll long long
int a[N],b[N];
int n,m;
char s[N],x[N];
void solve()
{
cin>>n>>m;
scanf("%s",s+1);
vector<int> cnt(n+10,0),pre(n+10,0);
for(int i=1;i<=n;i++)
{
if(s[i]=='A'){
pre[i]=-pre[i-1]-1;
cnt[i]=cnt[i-1]+1;
}
else{
pre[i]=pre[i-1]+1;
cnt[i]=cnt[i-1];
}
}
ll lastans=0;
while(m--)
{
ll l,r;
scanf("%lld%lld%s",&l,&r,x+1);
l=(lastans^l)%n+1;r=(lastans^r)%n+1;
if(l>r) swap(l,r);
int k=strlen(x+1);
ll xnum=0;
for(int i=1;i<=k;i++){
xnum=2ll*xnum+(x[i]-'0');
}
ll mod=(1ll<<k);
ll ans=0;
if((cnt[r]-cnt[l-1])%2){
ans=pre[r]+pre[l-1];
xnum=-xnum;
}
else{
ans=pre[r]-pre[l-1];
}
ans=((xnum+ans)%mod+mod)%mod;
for(int i=1;i<=k;i++){
cout<<((ans>>(k-i)&1));
}puts("");
lastans=ans;
}
}
signed main(){
//cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
int t=1;
//cin>>t;
while(t--) solve();
}
可以确定的是每个人为了最大化自己的贡献,当前一定会选择剩余菜中对自己最大的那个
那么顺着贪心会有问题,因为最后的人可能也会选这道菜,那么这样自己就会浪费一个机会,正确的贪心是从后往前贪心
#include<bits/stdc++.h>
using namespace std;
const int N = 2010;
#define ll long long
int n,m,k;
int a[N][N];
void solve()
{
cin>>n>>m>>k;
for(int i=0;i<n;i++){
for(int j=0;j<m;j++)
cin>>a[i][j];
}
vector<bool> st(m+10,false);
auto find=[&](int i){
int cur=-1,res=0;
for(int j=0;j<m;j++){
if(st[j]) continue;
if(cur<a[i][j]){
cur=a[i][j];
res=j;
}
}
return res;
};
vector<int> res;
for(int i=0,p=(k-1)%n;i<k;i++,p--){
if(p<0) p=n-1;
int mx=find(p);
st[mx]=true;
res.push_back(mx+1);
}
sort(res.begin(),res.end());
for(auto x:res) cout<<x<<" ";
cout<<"\n";
}
signed main(){
cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
int t=1;
cin>>t;
while(t--) solve();
}