牛客小白月赛116 题解

A 简单游戏

最大值的序号是否为给定数值,按题意输出即可。

a=list(map(int,input().split()))
print(["No","Yes"][max(a[:3])==a[a[3]-1]])

B 邪神的战斗力

可以看出 就是所有邪神的战斗力之和的 倍,所以我们对输入的 求和,再除以 就可以得到所有邪神的战斗力之和 。那么对于第 个邪神,她的战斗力就是

from sys import stdin

input=lambda:stdin.readline()
ri=lambda:int(input())
rl=lambda:list(map(int,input().split()))

n=ri()
a=rl()
s=sum(a)//(n-1)
print(*[s-a[i] for i in range(n)])

C Poi 的新加法 简单变体

发现 。(此处 指代二进制与位运算。)

本题中 。可以直接暴力运算通过本题。

from sys import stdin

input=lambda:stdin.readline()
ri=lambda:int(input())
rl=lambda:list(map(int,input().split()))

T=ri()
for _ in range(T):
	n,q=rl()
	a=rl()
	for __ in range(q):
		l,r=rl()
		cur=a[l-1]
		for i in range(l,r):
			cur=(cur&a[i])<<1
		print(cur)

D Poi 的消消乐

对于形如 AAAAA 的,可以直接消除到只剩一个

对于形如 AABBA 的,可以一直通过选择 消除到只剩 BA

对于形如 AAABB 的,由于最后一定会在开头留一个 A,最后只能通过选择 B 消除到不超过三个

注意题目并未保证大写字母一定是 AB

from collections import Counter
from sys import stdin

input=lambda:stdin.readline()
ri=lambda:int(input())
rl=lambda:list(map(int,input().split()))

T=ri()
for _ in range(T):
    n=ri()
    s=input()
    cnt=Counter(s)
    if cnt[s[0]]==n:
        print(1)
        continue
    sl=1
    while sl<n and s[sl]==s[0]:
        sl+=1
    if sl==cnt[s[0]]:
        print(1+min(3,n-sl))
    else:
        print(2)

E 旷课大师

原题解被证明为假题解。正在讨论。作为本场负责人,对牛客工作人员以及参赛者深感抱歉。

更新:

确定本场 Unrated。再次向牛客工作人员和参赛者表达我的歉意。

对于使用第一种能力的情况我们考虑二分答案,二分答案 后用 DP 检查可行性, 在第 天已经出席了 次的情况下,老师的怀疑值在全程不大于 的情况下,当前能达到的最小值。

对于第二种能力,由于怀疑值不会减小,我们可以考虑选出 天,并让这些天的 值和最大。对这个问题可以使用 DP 解决,设 表示当前取到第 天,已取了 次时因出席减少的怀疑值的最大值。

#include "bits/stdc++.h"
using namespace std;
typedef long long ll;
using ull=unsigned long long;
const ll INF=100000000000000;
ll a[30004]={0};
ll n,k,m;
bool check(ll maxn) {
    vector<vector<ll>> dp(n+5,vector<ll>(k+5,INF));
    dp[0][0]=0;
    for(int i=1;i<=n;++i){
        for(int j=0;j<=k;++j){
            if(dp[i-1][j]+a[i]<=maxn)
                dp[i][j]=min(dp[i][j],dp[i-1][j]+a[i]);
            if(j>0&&dp[i-1][j-1]!=INF)
                dp[i][j]=min(dp[i][j],dp[i-1][j-1]/2);
        }
    }
    return dp[n][k]!=INF;
}
void solve() {
    cin >> n >> k >> m;
    for (int i = 1; i <= n; ++i)
        cin >> a[i];
    ll ans1, ans2 = 0;
    if (k * m >= n) {
        ans2 = 0;
    } else {
        vector<ll> prefix_sum(n + m + 5, 0);
        for (int i = 1; i <= n; ++i)
            prefix_sum[i] = prefix_sum[i - 1] + a[i];
        vector<vector<ll>> dp(n + 5, vector<ll>(k + 5, 0));
        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= k; ++j) {
                dp[i][j] = max(dp[i][j], dp[i - 1][j]);
                if (i - m >= 0)
                    dp[i][j] = max(dp[i][j], dp[i - m][j - 1] + (prefix_sum[i] - prefix_sum[i - m]));
            }
        }
        ans2 = prefix_sum[n] - dp[n][k];
    }
    ll l = 0, r = ans2+7;
    while (l < r) {
        ll mid = (l + r) / 2;
        if (check(mid))
            r = mid;
        else
            l = mid + 1;
    }
    ans1 = l;

    cout << min(ans1, ans2) << endl;
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int T = 1;
//    cin>>T;
    while (T--) {
        solve();
    }
    return 0;
}

F Poi 的新加法 困难变体

发现 。(此处 指代二进制与位运算。)

由于每次运算只有在 当前位均为 1 的情况下,左移,而 ,可以发现 的情况下,这个值如果不为 0,最低位 一定已经大于等于 了,如果再进行下一次运算,由于,答案一定为 0。

from sys import stdin

ri=lambda:int(stdin.readline())
rl=lambda:list(map(int,stdin.readline().split()))
T=ri()
for _ in range(T):
	n,q=rl()
	a=rl()
	for __ in range(q):
		l,r=rl()
		cur=a[l-1]
		for i in range(l,r):
			cur=(cur&a[i])<<1
			if cur==0:
				break
		print(cur)

G 经典 DP

我们发现 的范围很小,这意味着每次乘以的 实际上种类不超过 ,所以我们可以先跑一遍 的值域dp,把和为 的所有方案数求出来,即求出 代表子段和为 的方案数。

然后我们考虑求出每一轮中可以使得 变为 的方案数,这可以双重循环进行转移,但是这样超时也爆空间,于是考虑矩阵快速幂优化,先跑出一轮中 的方案数 ,其中 ,求出每次的转移方程矩阵,再矩阵快速幂乘以初始矩阵(,其他位置均为 )跑一下即可。

#include<bits/stdc++.h>
#define print cout<<format
#define up(i,x,y) for (auto i=x;i<=y;i++)
#define down(i,x,y) for (auto i=x;i>=y;i--)
#define elif else if

using ll=long long;
using namespace std;

const ll mod=1000000007;

template<typename T=ll>
struct matrix{
	int n;
	vector<vector<T>>a;
	matrix (int _n): n(_n),a(_n,vector<T>(_n,0)) {}
	matrix operator* (matrix<T> &b){
		matrix<T> res{n};
		for (int i=0;i<n;i++)
			for (int j=0;j<n;j++)
				for (int k=0;k<n;k++)
					res[i][j]=(res[i][j]+a[i][k]*b[k][j]%mod)%mod;
		return res;
	}
	matrix operator* (matrix<T> &&b){ return (*this)*b; }
	vector<T>& operator[] (int y){ return a[y]; }
};

template<typename T=ll>
T qpow(T a,ll b){
    T res{a.n};
    for (int i=0;i<a.n;i++) res[i][i]=1;
    while(b){
            if (b&1) res=res*a;
            a=a*a;
            b>>=1;
    }
	return res;
}

void solve(){
	ll n;
	cin>>n;
	vector<ll>a(n+1);
	up(i,1,n) cin>>a[i];
	ll c,m,k,t;
	cin>>c>>m>>k>>t;
	c%=m;
	vector v(m,0ll);
	up(i,1ll,n){
		a[i]%=m;
		vector<ll> s(m,0ll);
		s[a[i]]=1;
		up(j,0,m-1) s[(a[i]+j)%m]=(s[(a[i]+j)%m]+v[j])%mod;
		up(j,0,m-1) v[j]=(v[j]+s[j])%mod;
	}
	matrix p(m);
	up(i,0ll,m-1){
		up(j,0ll,m-1){
			p[j][i*j%m]=(p[j][i*j%m]+v[i])%mod;
		}
	}
	matrix q(m);
	q[c][c]=1;
	auto res=q*qpow(p,t);
	print("{}",res[c][k]);
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int T=1;
    // cin>>T;
    while(T--) solve();
} 
全部评论
哥哥,您的E题题解是不是错了, 二分+贪心是错误的吧,考虑这组用例: 5 2 1 1 3 1 3 4 答案应该是4,您的输出5
6 回复 分享
发布于 昨天 21:08 广东
f居然没有    ios::sync_with_stdio(false); 就没过                     cin.tie(0),cout.tie(0);
3 回复 分享
发布于 昨天 22:09 辽宁
F题用Python写会超时
1 回复 分享
发布于 昨天 21:48 江苏
E题能重测吗?
1 回复 分享
发布于 昨天 21:19 北京
f题不关流竟然过不了,这场是不计rating了吗
点赞 回复 分享
发布于 昨天 22:46 江苏
f题那么简单?
点赞 回复 分享
发布于 昨天 21:57 甘肃
那个G题的状态转移方程怎么来的呀,有没有佬详细说一下
点赞 回复 分享
发布于 昨天 21:47 江西
E题的第一个样例,如果在第10天出勤,答案是不是可以是14啊
点赞 回复 分享
发布于 昨天 21:35 广东

相关推荐

评论
3
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务