马蹄集第六次oj赛

目录

动物们

赶deadline

散步

 迷宫

异或和

 抽奖

 海龟

矩阵取数

写程序

四柱河内塔


动物们


难度:黄金
©时间限制:1秒
巴占用内存:128M
有某类动物,可以在农场中待天,每天最多增加一只动物,第i天到来的动物每天
要吃的粮食为c[,现在初始粮食是X,问你在每天动物尽可能多的情况下最多容
纳几只动物?
注意:第讠天到来的动物,可以接纳也可以不接纳,如果接纳了就不可以中途再走
了。
格式
输入格式:第一行为n和X;
第二行为上述c[。
输出格式:输出一个整数,表示最多可以容纳的动物数量。 

#include <bits/stdc++.h>
using namespace std;
int ani[1005],dp[100005],n,x;
int main(){
cin >>n >>x;
for (int i=1;i<=n;i++){
cin >> ani[i];
ani[i] *= (n-i+1);
}
for (int i=1;i<=n;i++)
for(int j=x;j>= ani[i];j--)
dp[j]=max(dp[j],dp[j-ani[i]]+1);
cout <<dp[x];
return 0;
}

赶deadline


难度:钻石
0时间限制:1秒
巴占用内存:128M
小码哥有严重的拖延症,因此他经常赶deadline(即忙于要完成的任务)。有一天小N
码哥向你求助,因为要做的事太多了,只能舍弃一些相对不重要的。小码哥共有可
任务,每个任务有重要度I:和需要消耗的时间:。小码哥现在还有时间T,他希望
你帮忙写一个程序判断应该选择完成哪些任务使得完成的任务重要度之和最大。
格式
输入格式:第一行两个整数n(0<n<104),T(T<2000);
第2至n+1行输入第i项任务的重要度I:和完成需要的时间(0<
I,t<1000)。
输出格式:第一行一个整数,完成任务的重要度之和的最大值;
第二行若干个由空格隔开的整数,从小到大输出最优选择的任务的
序号(从1开始) 

#include <bits/stdc++.h>
using namespace std;
const int N = 1e4 +7;
int T,n,w[N],v[N],dp[N],path[N][N],ans[N];
int main(){
cin >>n >>T;
for(int i =1;i<=n;i++)
cin >>v[i]>>w[i];
for(int i=1;i<=n;i++)
for (int j = T;j >= w[i];j--)
   if (dp[j -w[i]]+v[i] > dp[j]){
       dp[j] = dp[j-w[i]] + v[i];
       path[i][j] = 1;
       }
cout<<dp[T]<<endl;
int i=n,j=T,cnt =0;
while (i>=1 && j){
if (path[i][j]){
ans[cnt++]=i;
j-=w[i];
}
i--;
}
for (int k = cnt-1;k >=0;k--)
cout <<ans[k]<<" ";
return 0;
}

散步


难度:黄金
0时间限制:1秒
巴占用内存:128M
小码哥今天去公园散步,公园里有一个环型的小道,因为小码哥想要刷一下步数,所
以他决定在小道上走m步。
现已知环形小道长度为,小码哥一步走1的距离,将小道坐标化:小码哥的初始位
置在1,顺时针分别是1n,到n后继续走就回到了1。
问小码哥有多少种走路方法,使得走m步过后回到原点(期间可以经过原点,只要
移动的序列不同就可以看作两个方法)。
注:小码哥只可以顺时针或逆时针走,不可以走半步,或是原地不动:
格式
输入格式:共一行,有两个用空格隔开的整数n,m(3≤n≤30,1≤m≤
30) 

#include <bits/stdc++.h>
using namespace std;
const int N = 37;
int dp[N][N],n,m;
int main(){
cin >>n >> m;
dp[0][0]=1;
for (int i = 1;i <= m;i++)
for (int j=0;j<n;j++)
dp[i][j]=dp[i-1][(j+1)%n]+dp[i-1][(j-1+n)%n];
cout << dp[m][0];
return 0;
}

 迷宫


难度:黄金
0时间限制:2秒
巴占用内存:128M
小码哥和他的手下在维多利亚的迷宫玩耍,小码哥并不喜欢这个项目,于是他决定以
最快的速度结束这个项目,这个迷宫可以看作是一个直角坐标系,小码哥在左下,终
点在右上点。
小码哥只从x,y轴的正方向走,因为这样是理论最快的解,问小码哥有多少种行走方
法来最快到达终点。
格式
输入格式:第一行两个整数m,n表示迷宫是m行n列;
接下来m行,每行n个数,描述了地图。
0-空地
1-墙(无法通过)
输出格式:一个整数表示答案
(mod2333)

#include <bits/stdc++.h>
using namespace std;
const int N = 3007;
const int mod = 2333;
int n,m,ans,a[N][N],dp [N][N];
int main(){
cin >>m >>n;
for (int i=m;i>=1;i--)
for (int j=1;j<=n;j++)
cin >>a[i][j];
dp[1][1]=1;
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++)
if(!a[i][j]){
dp[i][j]+=(dp[i-1][j]+dp[i][j-1]);
dp[i][j] %= mod;
}
cout <<dp[m][n];
return 0;
}

 

异或和


难度:钻石
心时间限制:1秒
巴占用内存:128M
给一个长度为n的序列a1,a2,.,an,寻找在a的所有递增子序列(可以为空)的
异或和中出现的数。
格式
输入格式:第一行一个正整数表示序列长度,
第二行n个整数表示序列a。
输出格式:第一行输出满足要求的数的个数:
第二行从小到大输出在α的所有递增子序列(可以为空)的异或和
中出现的数。

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 +7;
int n,a[N],dp [N];
int main(){
memset(dp,0x3f3f3f3f,sizeof dp);
dp[0]=0;
cin >>n;
for (int i=1;i<=n;i++)
cin>> a[i];
for(int i=1;i<=n;i++)
for (int j=0;j<=550;j++)
if(dp[j]<a[i])
dp[j^a[i]] = min(dp[j ^ a[i]],a[i]);
vector<int>ans;
for(int i=0;i<=550;i++)
if(dp[i] != 0x3f3f3f3f)
   ans.push_back(i);
cout << ans.size() << endl;
for (int id : ans)
cout <<id<<" ";
return 0;
}

 抽奖


难度:黄金
0时间限制:1秒
巴占用内存:128M
小码哥在集市上逛街,遇见了抽奖活动,抽一次2元,但是可能会抽出1,2,3,4
四种情况,他们是等概率的。
小码哥计划抽次,问亏本的概率是多少(即得到的奖金小于本金),小码哥赚了超
过一半本金的概率是多少(赚到的钱是奖金-本金后的部分)?
格式
输入格式:输入n表示小码哥连抽的次数。
输出格式:第一行输出亏的概率;
第二行输出赚超过一半本金的概率。
概率用最简分数表示,具体看样例。

#include <bits/stdc++.h>
using namespace std;
#define int long long
int n, dp[40][160],sum1,sum2,fenmu = 1,temp;
int gcd(int a,int b){return b ==0?a:gcd(b,a%b);}
signed main(){
cin >>n;
dp[1][1]=dp[1][2]=dp[1][3]=dp[1][4]=1;
for (int i=1;i<=n;i++)
  for (int j=i;j<=4*n;j++)
     for (int k=1;k <= 4;k++)
        if (j>k)
           dp[i][j]+=dp[i-1][j-k];
for (int i=n;i<2*n;i++)
   sum1 += dp[n][i];
for (int i=3*n+1;i<=4*n;i++)
   sum2 += dp[n][i];
for (int i=1;i<=n;i++)
fenmu *= 4;
temp = gcd(sum1,fenmu);
cout << sum1/temp <<"/"<<fenmu/temp <<endl;
temp = gcd(sum2,fenmu);
cout <<sum2 / temp <<"/"<<fenmu / temp;
return 0;
}

 海龟


号难度:钻石
0时间限制:1秒
巴占用内存:128M
很多人把L0G0编程语言和海龟图形联系起来。在这种情况下,海龟沿着直线移动,
接受命令T(转向180度)和F
(向前移动1单元)。
你会收到一份给海龟的命令清单。你必须从列表中精确地改变个命令(一个命令可
以被改变多次)。要求出海龟在遵循修改后的所有命令后,会从起点最远可以移到多
远?
格式
输入格式:第一行为命令清单,
第二行为需要改变的命令数。
输出格式:一行即为答案。

#include <bits/stdc++.h>
using namespace std;
#define int long long
string s;
int dp[101][51][2],n,INF=0x3f3f3f3f;
signed main(){
cin >>s >>n;
int size = s.size();
s=' '+s;
for (int i = 0;i<=size;i++)
   for (int j = 0;j<=n;j++)
       dp[i][j][0]=dp[i][j][1] =- INF;
dp[0][0][0] = dp[0][0][1]=0;
for (int i=1;i<=size;i++)
   for (int j=0;j<=n;j++)
       for (int k =0;k <= j;k++)
          if(s[i]=='F')
           if(k%2==1){
       dp[i][j][0]=max(dp[i][j][0],dp[i-1][j-k][0]);
       dp[i][j][1]=max(dp[i][j][1],dp[i-1][j-k][0]);
       }else{
       dp[i][j][0]=max(dp[i][j][0],dp[i-1][j-k][0]+1);
       dp[i][j][1]=max(dp[i][j][1],dp[i-1][j-k][1]-1);
       }
       else if (k%2==1){
       dp[i][j][0] = max(dp[i][j][0],dp[i-1][j-k][0]+1);
       dp[i][j][1] = max(dp[i][j][1],dp[i-1][j-k][1]-1);
       }else{
       dp[i][j][0] = max(dp[i][j][0],dp[i-1][j -k][1]);
       dp[i][j][1] = max(dp[i][j][1],dp[i-1][j-k][0]);
       }
       cout <<max(dp[size][n][0],dp[size][n][1]);
return 0;
}

矩阵取数


号难度:钻石
0时间限制:1秒
巴占用内存:128M
给定n*m的矩阵A,和一个整数飞,要求每行只能选取不超过一半的元素,且总
的选择元素的和要是飞的倍数,求满足条件的和的最大值。
格式
输入格式:第一行为n,m,k;
后n行为所述的矩阵。
输出格式:输出仅一行,为所求答案。
样例1
输入:343
复制
1234 

 

#include <bits/stdc++.h>
using namespace std;
int n,m,mod,ans;
int INF = 0x3f3f3f3f;
int a[75][75];
int dp[75][75][75];

int main(){
cin >>n >>m >>mod;
for(int i=1;i<=n;i++)
   for (int j=1;j<=m;j++)
      cin >>a[i][j];
memset(dp,-INF,sizeof(dp));
dp[0][0][0] = 0;
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++){
if(j==1){
  for (int k = 0;k <=m / 2;k++)
  for (int l=0;l < mod;l++)
     dp[i][0][l]=max(dp[i][0][l],dp[i-1][k][l]);
     }
for (int k=m /2-1;k >=0;k--)
  for (int l=0;l<mod;l++)
    dp[i][k+1][(l+a[i][j])%mod] = 
max(dp[i][k +1][(l + a[i][j])% mod],
dp[i][k][l]+a[i][j]);
}
for (int j=0;j<=m/2;j++)
 ans = max(ans,dp[n][j][0]);
 cout <<ans;
return 0;
}

异或和
难度:钻石
0时间限制:1秒
巴占用内存:128M
给一个长度为n的序列1,a2,.,am,寻找在a的所有递增子序列(可以为空)的
异或和中出现的数。
格式
输入格式:第一行一个正整数表示序列长度;
第二行n个整数表示序列a。
输出格式:第一行输出满足要求的数的个数:
第二行从小到大输出在α的所有递增子序列(可以为空)的异或和
中出现的数。

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 +7;
int n,a[N],dp [N];
int main(){
memset(dp,0x3f3f3f3f,sizeof dp);
dp[0]=0;
cin >>n;
for (int i=1;i<=n;i++)
cin>> a[i];
for(int i=1;i<=n;i++)
for (int j=0;j<=550;j++)
if(dp[j]<a[i])
dp[j^a[i]] = min(dp[j ^ a[i]],a[i]);
vector<int>ans;
for(int i=0;i<=550;i++)
if(dp[i] != 0x3f3f3f3f)
   ans.push_back(i);
cout << ans.size() << endl;
for (int id : ans)
cout <<id<<" ";
return 0;
}

写程序


难度:钻石
时间限制:1秒
巴占用内存:128M
有个程序员,每个程序员都可以写任意行代码,总共要编写
m行代码,这
m行代码可以由多个程序员来编写。但是第i个程序员在一行代码中会出现α
个bug。现在希望知道有多少种方案能使得这m行代码中的bug的数量不超过
b个。
两个方案不同当且仅当某个程序员编写的代码量(行数)不同。
格式
输入格式:第一行四个数n,m,b,mod,第二行为a[d。
输出格式:输出一行一个整数,表示m行代码bug数量小于b的方案数对
mod取模后的答案。 

#include<bits/stdc++.h>
#define N 505
using namespace std;

int n,m,b,mod,ans=0;
int a[N],f[N][N];

int main()
{
	scanf("%d%d%d%d",&n,&m,&b,&mod);
	for(int i=1;i<=n;i++)
	scanf("%d",&a[i]);
	f[0][0]=1;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			for(int k=a[i];k<=b;k++)
			f[k][j]=(f[k-a[i]][j-1]+f[k][j])%mod;
	for(int i=0;i<=b;i++)
	ans=(ans+f[i][m])%mod;
	printf("%d\n",ans%mod);
	return 0;
}

四柱河内塔


难度:黄金
时间限制:1秒
巴占用内存:128M
河内塔问题:有三个柱子,编号为1,2,3:在编号为1的柱子上有个大小不同圆
盘,圆盘从小到大,从上到下堆叠,你只可以移动一个柱子上最上面的圆盘。
现在你需要将编号为1的柱子上的圆盘移到3柱子上,顺序不变:
注意:你在移动过程中,不可以将大的圆盘放在小圆盘上,你一次只可以移动一个盘
子;
现在有一个4个柱子的河内塔,在规则不变的情况下,问最少需要移动多少次才能把
盘子从1号柱子移到4号柱子上。
格式
输入格式:一个整数f,表示n取(1,f)的f种情况。

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

using namespace std;
#define ll long long 
#define N 10000
const ll inf = 0x3f3f3f3f;
ll d[6000], f[6000];
int main()
{
    ll n;
    cin >> n ;
    for (ll i = 1; i <= n; ++i)
        d[i] = 2 * d[i - 1] + 1;
    memset(f, inf, sizeof f);
    f[0] = 0;
    for (ll i = 1; i <= n; ++i)
        for (ll j = 0; j <= i; ++j)
            f[i] = min(f[i], 2 * f[j] + d[i - j]);
    for (ll i = 1; i <= n; ++i)
        cout << f[i] << endl;
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值