马蹄集oj赛(双周赛第二十六次)

发布于:2024-05-10 ⋅ 阅读:(20) ⋅ 点赞:(0)

目录

斐波那契数列的组合

三国杀

数列分段

小码哥的跳棋游戏新编

能量供应

小码哥爱数字

最小串

小船过河

摘果子

泼墨淋漓

很重的枪

小码哥的布阵指挥


斐波那契数列的组合

#include<bits/stdc++.h> 
 
using namespace std;
 
// 斐波那契数列 1 1 2 3 5 8 13 21 34 55 89 144
 
int main( )
{
    int n;
    int temp = 0;
    cin >> n;
    vector<int> v;
    v.insert(v.end(), 0); 
    v.insert(v.end(), 1);
    
	for(int i=1;i<n;i++){
		temp = v[i]+v[i-1];
		if(temp>n){
			break;
		}
    	v.insert(v.end(),temp);
	}
	
    int len = v.size()-1;
    int sum = 0;
    int num = 0;
    
	for(int i=len;i>0;i--){
		sum += v[i];
		num++;
		if(sum>n){
			sum -= v[i];
			num--;
		}
		else if(sum==n){
			cout << num ;
			break;
		}
		else{continue;}
	}
	
    return 0;
}

三国杀


少难度:黄金时间限制:1秒四占用内存:128 M
小码哥和小码妹酷爱三国杀。在一局游戏中,每人有n名武将,每名武将有一个武力值。每一回合,每人挑选一名武将作战,武力值大的获胜,同时该武将进入弃牌堆。如果提前知道了小码妹的出牌顺序,小码哥能最多获胜几回合?
格式
输入格式:第一行包含一个正整数n;第二行 n 个正整数 ai,表示小码哥的武将第三行 n 个正整数 b ,表示小码妹的武将。
输出格式:一个整数,输出小码哥最多获胜的回合数。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

int i,j,k,n,m,t,a[1000005];
multiset<int> s;

int main() {
  cin>>n;
  for(i=1;i<=n;i++){
    cin>>k;
    s.insert(k);
  }
  for(i=1;i<=n;i++) cin>>a[i];
  sort(a+1,a+n+1);
  for(i=n;i>=1;i--){
    auto it = s.upper_bound(a[i]);
    if(it!=s.end()){
      s.erase(it);
      t++;
    }
  }
  cout<<t;
  return 0;

}

数列分段


巴 占用内存:128 M少难度:黄金时间限制:1秒
对于给定的一个长度为N的正整数数列 A;,现要将其分成连续的若干段,并且每段和不超过M(可以等于 M),问最少能将其分成多少段使得满足要求。
格式
输入格式:第一行包含两个正整数 N,M ,表示了数列 A,的长度与每段和的最大值,第二行包含 N 个空格隔开的正整数 A;,如题目所述。
输出格式:一个正整数,输出最少划分的段数。

def main():
    #code here
    N,M=map(int, input () .split ())
    num=list(map(int, input () .split ()))
    s=0
    res=1
    for i in range(N):
        if s+num[i]<=M:
            s+=num[i]
        else:
            res+=1 
            s=num[i]
    print(res)
    pass


if __name__ == '__main__':
    main();

小码哥的跳棋游戏新编


了难度:黄金时间限制:1秒四占用内存:128M
小码哥喜爱跳棋。跳棋游戏在一条直线上,一共几个位置(1~n),每个位置有3个状态:0表示没有棋子,1表示红棋子,2表示蓝棋子。在起始的点(坐标为8)没有棋子。小码哥的棋子自然是能通过没有棋子的位置。当面前有1个棋子时,小码哥可以直接跳过。当有两个及以上不同颜色棋子连在一起时,小码哥的棋子是跳不过去的。这时候,就要花费能量,破坏掉一些棋子,才能跳过。但小码哥的棋子是经过升级的,如果一连串相同颜色的棋子在一起时,小码哥是可以直接跳过的。已知破坏一枚棋子需要花费一点能量。现在求小码哥到达终点(坐标为几+1)需要花费至少多少能量?
格式
输入格式:第一行包含一个正整数 n;
第二行 n 个整数 a;(1 <i< n),表示棋盘的状态。
输出格式:一个整数,输出最小耗费的能量数。

#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 7;
int a[N];
int main()
{
    int n;
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
    }
    int ans = 0;
    for (int i = 1; i <= n; i++) {
        if (a[i] && a[i - 1] && a[i] != a[i - 1]) {
            a[i] = 0;
            ans++;
        }
    }
    cout << ans << endl;
    return 0;
}

能量供应


难度:钻石时间限制:1秒巴 占用内存:128 M
最近小码哥迷上了一款建造管理类游戏,游戏中的设施需要能量塔提供能量,设施运行时需要一定数量的能量塔在附近才能运作,不同的设施需要的能量塔的数量以及能链接到能量塔的范围也不一样,超出设施链接范围的能量塔无法为设施提供能量,不同设施可以重复利用同一座能量塔。
现在小码哥修建了一条长为n的道路来放置能量塔,但能量塔的修建成本稍高,小码哥不想花太多时间收集资源建造过多能量塔,现在小码哥用一个区间s,e告诉你每个设施链接到能量塔的有效范围,以及每个设施需要的能量塔数量t,请你告诉他最少修建多少个能量塔即可让所有设施运作?
格式
输入格式:两个正整数 n,b,表示道路的长度和设施的数量;接下来6行每行三个正整数 s,e,t,表示设施的链接范围的起始和结尾以及需要的能量塔数量。

#include<bits/stdc++.h>
using namespace std;
typedef long long int LL;
 const int maxn = 100005;
 int n, b;
 vector<int> se[maxn];
 vector<int> st[maxn];
 int ans[maxn], len[maxn];
 int main() {
 cin >> n >> b;
 for(int i = 1; i <= b; i++) {
 int s, e, t;
 cin >> s >> e >> t;
 se[s - 1].push_back(e);
 st[s - 1].push_back(t);
 len[s - 1]++;
 }
 for(int i = 0; i <= n; i++) {
 if(i != 0) ans[i] = max(ans[i - 1], ans[i]);
 for(int j = 0; j < len[i]; j++) {
 ans[se[i][j]] = max(ans[se[i][j]], ans[i] + st[i][j]);
 int tt = ans[se[i][j]] - se[i][j];
 for(int k = i + 1; k < se[i][j]; k++)
 ans[k] = max(ans[k], tt + k);
 }
 
 }
 cout << ans[n];
 return 0;
 }

小码哥爱数字


难度:钻石◎ 时间限制:1秒巴占用内存:128 M
小码哥很喜欢数字,有一天他找到老师给他出一道有关数字的题目。老师给他一个位数很多的正整数N(不超过 250位),让小码哥去掉其中任意k个数字后剩下的数字按原左右次序将组成一个新的非负整数。小码哥觉得老师在刁难他(因为小码哥才一年级),所以他找身为程序员的你编程对给定的N 和k寻找一种方案使得剩下的数字组成的新数最小。
格式
输入格式:(正整数,不超过250位),不必考虑前导0;入
(需要删除的数字个数),保证有输出,即 k小于n的位数。k
输出格式:最后剩下的最小数。

from collections import deque,Counter
from queue import PriorityQueue

def main():
    #code here
    s = str(int(input()))
    k = int(input())
    n = len(s)

    bits = n-k;
    que = PriorityQueue()
    for i in range(n-bits):
        que.put((s[i],i))

    cur_pos = -1
    ans = []
    all_zero = True
    pos = None
    for i in range(n-bits,n):
        que.put((s[i],i))

        while que.queue[0][1] <= cur_pos:
            que.get()

        v,idx = que.get()
        ans.append(v)
        if v!= '0':
            if all_zero:
                pos = len(ans)-1
                all_zero = False
        
        cur_pos = idx
    
    if all_zero:
        print(0)
        return 
    
    print(''.join(ans[pos:]))

if __name__ == '__main__':
    main();

最小串


少 难度:钻石时间限制:1秒巴 占用内存:128 M
给定一个由 8,组成的字符串S。可以交换相邻,1或1,2的位置(例1210)请输出原字符串经过任意转换后字典序最小的字符串。原字符串如:1221013长度不超过 105
格式
输入格式:字符串 S
输出格式:转化后字典序最小的字符串

#include <bits/stdc++.h>
 using namespace std;
 void solve() {
 string str, res; cin >> str;
 int n = str.length(), one = 0;
 for (int i = 0; i < n; ++i) one += str[i] == '1';
 for (int i = 0; i < n; ++i)
 if (str[i] == '2') {
 res += string(one, '1');
 for (int j = 0; j < n; ++j)
 if (str[j] != '1')
 res += str[j];
 cout << res << "\n";
 return;
 } else if (str[i] == '0') {
 int zero = 0, p = i;
 while (p < n && str[p] != '2') zero += str[p++] == '0';
 res += string(zero, '0');
 res += string(one, '1');
 for (int j = p; j < n; ++j) if (str[j] != '1') res +=str[j];
 cout << res << "\n";
 return;
 }
 cout << str << "\n";
 }
 int main() {
 ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
 solve();
 return 0;
 }

小船过河


难度:黄金。时间限制:1秒四占用内存:128 M
几个人想要过河,但现在只有一条小船(有船夫)。小船每次最多载两人过河(不考虑船夫),且有最大承载重量t。请计算小船最少要来回几次。
格式
输入格式:第一行输入2个整数n和t(0 <n<10',0<t< 232 );第二行输入 n个整数代表每个人的体重(范围:[1,232-1],均小于t)。
输出格式:输出一个整数。

#include <bits/stdc++.h>

 using namespace std;

 int main() {
 cin.tie(NULL)->ios_base::sync_with_stdio(false);
 int n, m;
 cin >> n >> m;
 vector<int> v(n);

 for (auto &x : v)
 cin >> x;

 multiset<int> s;

 for (auto x : v)
 s.insert(x);

 int ans = 0;

 while (!s.empty()) {
 auto x = *s.rbegin();
 s.erase(s.find(x));

 if (!s.empty() && s.upper_bound(m - x) != s.begin())
 s.erase(prev(s.upper_bound(m - x)));

 ++ans;
 }
 cout << ans << endl;

 return 0;
 }

摘果子


难度:钻石时间限制:1秒巴 占用内存:128 M
在一个果园中,有几种果树,他们分布在一条数轴上,有独立的坐标。小码哥被奖励了许多果子,但是这些果子需要他自己去摘,小码哥摘一次果子需要1分钟。
现在小码哥在第一颗果树下开始行走,从“棵走到“-1棵需要t;的时间。如果小码哥选择在这棵果树下摘,那么第一个1分钟将会摘下 ai的果子,第二次摘将摘下 ai-d;个果子,第三次将摘下 ai-2*d个果子,以此类推。但是小码哥的时间有限,只有t的总时间来摘果子。
请你帮助他算出,可以摘下的最大果子数是多少?
格式
输入格式:第一行输入正整数 n,t;第二行 n 个数,表示第一次可以摘的果子数 ai;第三行 n 个数,表示每次摘减少的可摘数 d;第四行几-1个数,表示数之间的间隔行走时间t

#include<bits/stdc++.h>
 using namespace std;
 int n,m,ct;
 long long ans;
 long long f[30][200005];
 int a[30],d[30],t[30];
 priority_queue<int>q;
 void solve(int w){
int sum=m-t[w];
 long long rans=0;
 if(sum<0) return ;

 for(int i=1;i<=w;i++){
 int ct=a[i];
 for(int j=1;j<=sum;j++){
 q.push(ct);
 ct-=d[i];
 if(ct<0) break;
 }
 }

 while(sum>0 && !q.empty()){
 rans+=q.top();
 q.pop();
 sum--;
 }
 ans=max(ans,rans);
 while(!q.empty()) q.pop();
 }
 int main(){
 cin>>n>>m;
 for(int i=1;i<=n;i++) cin>>a[i];
 for(int i=1;i<=n;i++) cin>>d[i];
 for(int i=2;i<=n;i++) cin>>t[i];
 for(int i=3;i<=n;i++) t[i]+=t[i-1];

 for(int i=1;i<=n;i++) solve(i);
 cout<<ans;
 return 0;
 }

泼墨淋漓


。时间限制:1秒四占用内存:128 M乡难度:黄金
小码哥有 n幅画,每幅画都有一个编号 ;,编号为非负数且可以相同。他想改变一些画的编号,使得幅画使用的不同编号数量不超过 k(1<k<n<200000),问最少需要改变多少幅画的编号?n
格式
输入格式:第一行输入 n,k;
第二行输入 ai。
输出格式:输出需要改变编号的画的最少数量。

#include<bits/stdc++.h> 

using namespace std;

int n,k;
map<int,int> cnt;
vector<int> a;
int main( )
{
    cin>>n>>k;
for (int i=1,x;i<=n;++i){
cin>>x;
if(cnt.count (x))++cnt[x];
else cnt [x]=1;
}
for (map<int,int>::iterator it=cnt.begin();it!=cnt.end();++it)a.emplace_back(it->second);
sort (a.begin(),a.end ());
if(a.size()<=k){cout<<0<<endl;return 0;} 
int sum(0);
for (int i=1;i<=k;++i)
sum+=a[a.size()-i];
cout<<n-sum<<endl;
    return 0;
}

很重的枪


难度:白银巴: 占用内存:128 M时间限制:1秒
小码哥在玩打怪游戏,他的面前有n个怪,第个怪的血量为 a;。对于一个怪物,他有两种攻击方式:
1.使用 a次普通攻击消灭该怪物;
2.施放一次技能消灭该怪物。
小码哥最多只能使用 k 次技能,他想知道最少使用多少次普通攻击就可以消灭所有怪物。
格式
输入格式:第一行输入 n,k;
第二行输入 ai。
其中:0≤ai≤10°,1≤k<n<2x105
输出格式:输出使用普通攻击的最少次数

#include<bits/stdc++.h> 

using namespace std;
int a[200010];
int main( )
{
    int i,j,k,m,n;
    long long sum=0;
    scanf("%d%d",&n,&k);
    for(i=1;i<=n;i++){
        scanf("%d",&a[i]);
    }
    sort(a+1,a+n+1);
    for(i=1;i<=n-k;i++){
        sum+=a[i];
    }
    printf("%lld\n",sum);
    return 0;
}

小码哥的布阵指挥


少难度:黄金◎时间限制:1秒巴占用内存:128 M
小码哥手上有几 个部队,驻扎在一条马路上,可以把这个马路看作一条轴,小码哥的指挥所在原点,第i个部队在 a”的位置,现在重新布置部队的位置,设布置后的位置为bi,要求bi>ai,且每个部队之间的距离大于等于 X
说明:部队从第1个开始按顺序进行处理。一旦处理完,位置就不再发生变化。所以你需要做出对于每只部队来说,当前情况下最优解(当前情况指,序号在他之前的部队已经更新过后的情况),即在满足上述条件下,部队离小码哥越近越好。
格式
输入格式:第一行两个整数 n,X
第二行 n 个整数,表示 a[]。

#include<bits/stdc++.h> 

using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;
#define rall(a) a.rbegin(), a.rend()
#define fi first
#define se second
#define rep(i,s,n) for(int i=s;i<n;i++)
#define repd(i,s,n) for(int i=s;i>=n;i--)
const int MOD=1e9+7;
const int maxN=5e3+1;
 const int INF=2e9;
 const int MB=20;
 const int MAX_LEN=200001;
 ull s[MAX_LEN];
 ull p[MAX_LEN];
 void solve()
 {
 ll n,x;
 cin>>n>>x;
 rep(i,0,n)
 {
 cin>>s[i];
 p[i]=s[i];
 }
 ll pre=s[0];
 rep(i,1,n)
 {
 sort(p,p+i);
 ll temp;
 rep(j,0,i)
 {
 temp=p[j]+x;
 if (j==i-1)
 break;
 else
 {
 if (p[j+1]-temp>=x)
 break;
 }
 } 
 s[i]=temp>s[i]?temp:s[i];
 p[i]=s[i];
 }
 rep(i,0,n)
 cout<<s[i]<<" " ;
 }
 int main()
 {

 solve();
 return 0;
 }