暑期训练赛三

1919: kirito's 星爆气流斩
时间限制: 2 Sec  内存限制: 128 MB
提交: 148  解决: 37
[提交][状态][讨论版]
题目描述

  主角kirito是使用世界首款完全潜行游戏“刀剑神域(Sword Art Online)”的玩家。曾经很幸运的参与过封闭测试,并买下正式版的kirito,正准备体验游戏的第一次正式营运。但在登入后不久,kirito发现“登出”指令竟然消失,而与此同时自称是SAO游戏设计者“茅场晶彦”的人说:“无法完成攻略就无法离开游戏,只有打倒位于“艾恩葛朗特”顶楼,第100层的头目-达成“完全攻略”才是离开这个世界唯一的方法。并且,在游戏内GAME OVER或是尝试脱下NERvGear,玩家会立刻被NERvGear发出的高频率微波破坏脑部而死亡。”唯有接受这个矛盾事实的人,才能够存活下去。
  自己也被卷入其中的kirito,在游戏的舞台——巨大浮游城堡“艾恩葛朗特”里,以不与人组队的独行剑士身份,逐渐崭露头角,并获得“黑色剑士”的称号。kirito以完全攻略的条件——到达城堡最上层为目标,持续进行严酷且漫长的冒险,在这期间他邂逅了女性细剑使——“闪光”亚丝娜,以及公会“血盟骑士团团长”希兹克利夫,他的命运也一步步产生了巨大的变化。kirito能否从游戏里全身而退……

由于kirito是封弊者,kirito有一个二刀流技能,可以使用星曝气流斩,斩杀了强大的守关BOSS。

但是星曝气流斩需要很庞大的法力值。
现在商店有N个药品,kirito的物品栏有W的容量。
第i个药品有重量w_i,可以恢复法力值v_i,有数量c_i个。
现在请你帮助kirito计算他可以恢复的最大法力值。

输入
第一行两个整数N,W(1 <= N <= 300,1 <= W <= 500000 )
接下来N行,每行三个整数w_i,v_i,c_i(1 <= w_i <= 10000,1 <= v_i <= 10000, 1 <= c_i <= 500)

输出
输出一个整数

样例输入
3 6
2 2 5
3 3 8
1 4 1
样例输出
9
提示
来源


czq

[提交][状态][讨论版]

知识点:多重背包+优化

心得:这道题一开始就确定了是多重背包,但我对背包问题还不是很熟,就没做。

思路:就是将背包的数量分成几个小块,像7=1+2+4这样,对多重背包起到优化作用。

#include<bits/stdc++.h>
using namespace std;
const int maxn=300;
const int maxc=500;
const int maxw=500000;
int f[maxw+5],we[maxc*maxn+5],vu[maxn*maxc+5];
int main(void)
{
	int n,w,i,j;
	while(~scanf("%d%d",&n,&w))
	{
		int wi,vi,ci,cnt=0;
		memset(f,0,sizeof(f));
		for(i=0;i<n;i++)
		{
			scanf("%d%d%d",&wi,&vi,&ci);
			for(j=1;j<=ci;j<<=1)
			{
				we[cnt]=j*wi;
				vu[cnt]=j*vi;
				ci-=j;
				cnt++;
			}
			if(ci>0)
			{
				we[cnt]=ci*wi;
				vu[cnt]=ci*vi;
				cnt++;
			}
		}
		for(i=0;i<cnt;i++)
		{
			for(j=w;j>=we[i];j--)
			if(f[j]<f[j-we[i]]+vu[i])
			f[j]=f[j-we[i]]+vu[i];
		}
		printf("%d\n",f[w]);
	}
	return 0;
}

1951: ly和wjw的无聊游戏
时间限制: 1 Sec  内存限制: 128 MB
提交: 60  解决: 20
[提交][状态][讨论版]
题目描述
 众所周知,ly和wjw是好朋友,某天特别无聊,他们想自己编一个游戏代码,无奈水平有限,只会写个random每次输出一个随机数,于是他们自己制定了一个游戏规则
游戏由多轮组成,每一轮中由计算机输出一个自然数$k_i$,然后ly和wjw会同时喊出一个数字,谁喊出的数字更靠近这个$k_i$就获胜,获胜的人的得分会乘上$k_i^2$,失败者的得分乘上$k_i$.
虽然这个游戏很无聊,但是为了打发时间,ly和wjw居然玩了一下午,但是由于记录游戏步骤的ly弄丢了他们记录T场游戏的笔记本,但是好在wjw还依稀记得每场比赛最终的结局是ly获得了$a_i$分,wjw获得了$b_i$分。但是他的记忆是模糊的,他希望能够验证没对$a_i$和$b_i$是否正确。
每场游戏一开始ly和wjw的积分都是$1$.
wjw和ly不想太麻烦你,他们只想知道对于每组ai和bi的结局是否是一个正确的最终得分。

输入
 第一行输入一个T,表示总共进行了$T$组游戏$\left(T \leq 500000\right)$
接下来的$T$行,每行两个整数$a_i$和$b_i$表示wjw记得的每一场比赛两人的最终得分$(1<=a_i,b_i<=10^9)$

输出
 对于每一对$a_i$和$b_i$,如果这对最终得分是正确的,那么输出"$Ok$",否则输出"$Error$".

样例输入
4
16 16
2 4
1 1
18 19
样例输出
Error
Ok
Ok
Error
提示
来源
jnxxhzz

[提交][状态][讨论版]

错误原因:当时想先算出a,b的最大公约数c,再求出a1=a/c,b1=b/c,最后如果a1*b1==c,就成立,表面上看挺对的,

但数据太大了,求公约数和除数都是问题,用longlong也不对,后来就没做出来。

思路:参考了学长的代码,考虑a*b是一个数的3次方,可以作为判断条件之一,但也可能存在1,27的情况,也是不符合题意的。因此,如果a*a%b==0&&b*b%a==0成立,就最终成立。

心得:a*b,从3次方考虑。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
int f(LL a,LL b)
{
    LL l=0,r=1000000;
    while(l<=r)  //二分查找方便快捷。
    {
        LL m=(l+r)/2;
        if(m*m*m==a*b) return 1;
        else if(m*m*m<a*b) l=m+1;
        else if(m*m*m>a*b) r=m-1;
    }
    return 0;
}
int main(void)
{
    LL a,b;
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%lld%lld",&a,&b);
        if(a*a%b==0&&b*b%a==0&&f(a,b)) printf("Ok\n");
        else printf("Error\n");
    }
    return 0;
}

问题 B: 大一上之初出茅庐
时间限制: 1 Sec  内存限制: 128 MB
提交: 744  解决: 211
[提交][状态][讨论版]
题目描述
四年的前的今天,你正想着我应该去哪里上什么样的大学,你想你会学…,结果是很幸运的来到了浙江中医药大学,啊哈,既然来了,就不废话了,这个时候的你应该可以帮我算算A+B。给你你俩数,你把第一个数的奇数位的数与第二个数的偶数位的数相加得到一个数,再把第一个数的偶数位和第二个数的奇数位相加得到一个数,再输出这两个新得到的数的和。

输入
输入两个数A,B《范围不超过 long long 》

输出
输出上述和

样例输入
123
456
样例输出
21
提示
[提交][状态][讨论版]

心得:这道题一开始用string,不符合题意,后来改为多longlong和组数据就行了。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
int main(void)
{
    LL a,b;
    while(~scanf("%lld%lld",&a,&b))
    {
        LL sum=0,tp;
        while(a)
        {
        tp=a%10;
        a/=10;
        sum+=tp;
        }
        while(b)
        {
        tp=b%10;
        b/=10;
        sum+=tp;
        }
        printf("%lld\n",sum);
    }
    return 0;
}

问题 J: 不存在的泳池
时间限制: 1 Sec  内存限制: 128 MB
提交: 246  解决: 92
[提交][状态][讨论版]
题目描述
小w是云南中医学院的同学,有一天他看到了学校的百度百科介绍:
截止到2014年5月,云南中医学院图书馆纸本藏书74.8457万册,纸质期刊388种,馆藏线装古籍图书1.8万册,电子资源总量35TB,拥有中、外文数据库25个,电子图书29.5万册(镜像)、包库130万册。古籍线装图书1.8万余册,有39种列为本馆珍善本,如《彻滕八编》、《赵氏医贯》等明清版本、台湾文渊阁版本《四库全书》,按《全国古籍善本书总目》分类表(即:经·史·子·集四部分类)部编列、上架、供读者使用。
显然学校图书馆的占地面积非常大,于是他开始想象.....如果他有一个跟图书馆一样大的游泳池?!
如果有一个那么大的游泳池,他就可以邀请女神一起去游泳...
如果有一个那么大的游泳池,他还可以划开一半出租,收取门票费赚钱...这样等赚了一些钱之后,就招一些游泳教练来,然后对外招生,招收学生继续赚更多的钱!
如果有一个那么大的游泳池,他还能把泳池里的水全部放光...开一个吕子乔心目中最大最棒的泳池派对!
.......
等有了更多的钱,就可以在第一个泳池旁边再建一个一样大的泳池......
小w一边流口水一边想自己的未来,一想到女神看到自己事业有成,靠一个游泳池白手起家发家致富,对自己投怀送抱,高兴的根本合不拢嘴。
这时候旁边的小q作为小w的室友,随口提了一句:“这么大的泳池,你怎么换水?”
显然小w是个有原则的人,他不会让自己的泳池像不法商家一样不换水,用不干净的水给别人使用或者给自己使用。
小w百度了之后发现...淘宝里有一家店卖一种一次性抽水机,这种一次性抽水机很神奇,它有两个按钮:
1.如果泳池里的水(立方米)是3的倍数,那么可以按第一个按钮让它抽走泳池里三分之二的水
2.如果泳池里的水(立方米)是2的倍数,那么可以按第二个按钮让它抽走泳池里二分之一的水
小w虽然是个有原则的人,但是作为一个商人,他需要节省钱...而且他现在有两个泳池....但是显然这种抽水机不能把水抽光,水越少,性价比就越低。
但是两个泳池建在一起,如果两个泳池的水面不一样高,那么小w会很不开心,所以他想用这种抽水机,把两个泳池里的水抽成一样多。然后再考虑别的....当然在保证能把两个泳池里的水抽成一样多的情况下..他希望花的钱最少...
(不管了!好看最重要,好看才能吸引顾客啊!先好看!再考虑怎么换水吧)

输入
多组测试数据,给出A,B表示两个泳池当前的水量(立方米)

(1<=A,B<=10^9)

输出
每组测试数据输出一个整数表示至少需要买多少个一次性抽水机,若买多少个都不能让泳池的水相等,则输出"-1"

样例输入
5 20
14 8
6 6
样例输出
2
-1
0
提示
 显然这一切都是他的YY,他怎么可能会有游泳池???

[提交][状态][讨论版]
中文  English  

心得:一开始陷入思维定式了,一直以为比大小,后来发现直接统计次数之和就行了。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
LL gcd(LL a,LL b)
{
    return b==0?a:gcd(b,a%b);
}
int main(void)
{
    LL a,b;
    while(~scanf("%lld%lld",&a,&b))
    {
        if(a==b) printf("0\n");
        else
        {
            if(a<b) swap(a,b);
            LL k=gcd(a,b);
            LL k1=a/k,k2=b/k;
            LL n1=0,n2=0;
            while(k1%2==0) k1/=2,n1++;
            while(k1%3==0) k1/=3,n1++;
            while(k2%2==0) k2/=2,n2++;
            while(k2%3==0) k2/=3,n2++;
            if(k1==1&&k2==1)
            {
                printf("%lld\n",n1+n2);
            }
            else printf("-1\n");
        }
    }
    return 0;
}

问题 E: 喜闻乐见的a+b
时间限制: 1 Sec  内存限制: 128 MB
提交: 365  解决: 136
[提交][状态][讨论版]
题目描述
喜闻乐见的a+b来了,当然二进制,八进制,十进制什么的估计你们也懒得写了,来个20进制的a+b

输入
         给出多组a和b,每个数字一行

数字由0~9和小写字母a~j(10~19)

给出的长度不超过100

输出
每组数据输出a+b的和。

样例输入
1234567890
abcdefghij
99999jjjjj
9999900001
样例输出
bdfi02467j
iiiij00000
提示
[提交][状态][讨论版]

心得:一开始是设的a,b,c三个字符数组,然后错了,

这种进制转换的题一点要考虑

1、进位问题,8,20等为要如何进位。

2、数的正负,符号一定要记得去掉。

3、运算时都是整数,一般是从后往前运算。

4、前导零一定要消除。

5、超过十进制的,存储用int数组,输出判断是否>10。

#include<bits/stdc++.h>
using namespace std;
char a[120],b[120];
int a1[120],b1[120],c[120];
int main(void)
{
    while(~scanf("%s",a))
    {
        scanf("%s",b);
        int i,j,k;
        int l1=strlen(a);
        int l2=strlen(b);
        int l=max(l1,l2);
        memset(a1,0,sizeof(a1));
        memset(b1,0,sizeof(b1));
        memset(c,0,sizeof(c));
        for(i=0,j=l1-1;i<j;i++,j--)
        swap(a[i],a[j]);
        for(i=0,j=l2-1;i<j;i++,j--)
        swap(b[i],b[j]);
        for(i=0;i<l1;i++) 
        {
            if(a[i]>='0'&&a[i]<='9') a1[i]=a[i]-'0';
            else if(a[i]>='a'&&a[i]<='j') a1[i]=(a[i]-'a')+10;
        } 
        for(i=0;i<l2;i++)
        {
            if(b[i]>='0'&&b[i]<='9') b1[i]=b[i]-'0';
            else if(b[i]>='a'&&b[i]<='j') b1[i]=(b[i]-'a')+10;
        }
        i=0;
        while(i<l)
        {
            c[i]=a1[i]+b1[i]+c[i];
            if(c[i]>=20)
            {
                c[i]=c[i]-20;
                c[i+1]++;
            }
            i++;
        }
        k=i+1;
        while(c[k]==0&&k>=0) k--;
        if(k<0) printf("0\n");
        else
        {
            for(;k>=0;k--)
            {
                if(c[k]>=0&&c[k]<=9) printf("%d",c[k]);
                else printf("%c",(c[k]-10)+'a');
            }
            printf("\n");
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41829060/article/details/81148191