2023牛客暑期多校训练营2

题目顺序不分难度

KBox

状态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();
}

ILink 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();
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值