A | 托米的赌球 |
链接:https://www.nowcoder.com/acm/contest/156/A
来源:牛客网
题目描述
紧张刺激的世界杯正在进行中(在托米的世界线里),欧洲人托米沉迷于赌球无法自拔。
托米的口袋里有 100 元,50元,20元,10元,5元,2元,1元的纸币,50分,20分,10分,5分,2分,1分的硬币各无限个。
托米计划买下几注 a 元 b 分的彩票,他希望能支出的纸票数量和硬币数量之和最小,他希望你帮助他完成这个任务。同时由于彩票亭不支持找零,托米希望他的支出恰好等于 a 元 b 分
输入描述:
第一行输入一个正整数 T下面 T 行每行两个整数 a,b
输出描述:
每行输出 13 个正整数 n1 ...n13, 对应题面顺序给出最小化支出纸票数量和硬币数量之和的情况下,每种货币的使用次数,如果有多种方案,输出字典序最大的一种,注意这里字典序是依次比较n1到n13,而不是简单的把 13 个正整数拼接在一起
示例1
输入
复制
2 1 5 2 4
输出
复制
0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 2 0
备注:
T=100,0≤ a≤ 109, 0≤ b<100
题解:水题,贪心
#include<stdio.h>
#include<string.h>
#include<map>
#include<algorithm>
using namespace std;
int aa[]={100,50,20,10,5,2,1};
int bb[]={50,20,10,5,2,1};
int main(){
int t,a,b;
scanf("%d",&t);
while(t--){
int m1[105]={0},m2[105]={0};
scanf("%d %d",&a,&b);
for(int i=0;i<=6;i++){
while(a>=aa[i]){
m1[aa[i]]++;
a-=aa[i];
}
}
for(int i=0;i<=5;i++){
while(b>=bb[i]){
m2[bb[i]]++;
b-=bb[i];
}
}
printf("%d %d %d %d %d %d %d %d %d %d %d %d %d\n",m1[100],m1[50],m1[20],m1[10],m1[5],m1[2],m1[1],m2[50],m2[20],m2[10],m2[5],m2[2],m2[1]);
}
return 0;
}
B | 托米的划分 |
链接:https://www.nowcoder.com/acm/contest/156/B
来源:牛客网
题目描述
欧洲人托米非常喜欢数字,他经常在空闲时玩下面的游戏
对于一个数字 n, 托米会随性选中一个数 p, (1 < p <= n), 将 n 拆分成 ,v=n-u,并对 u,v 重复这个过程,直到他有了 n 个 1
1317 为了挑战托米,在每次托米进行划分时,会给托米奖励 u * v 的分数,托米希望你能帮他最大化他的得分。
输入描述:
第一行一个正整数 T下面 T 行每行一个正整数 n
输出描述:
对于每组数据,输出托米的最大得分
示例1
输入
复制
1 5
输出
复制
10
备注:
T≤ 104, n≤ 109
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
typedef long long ll;
int main(){
int t,n;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
ll ans=1ll*(n+1)*n/2;
printf("%lld\n",ans-n);
}
return 0;
}
D | 托米的咒语 |
链接:https://www.nowcoder.com/acm/contest/156/D
来源:牛客网
题目描述
托米没有完成上一个任务,准备施展黑魔法推倒 1317
黑魔法咒语被描述为一个 长为 n 的,仅包含小写英文字母 'a'...'i' 的字符串,在托米所在的星球,魔法造成的每次有效伤害都是来自他的一个子序列,对于每一个 'a'... 'i' 的排列(共 9! 种),若作为咒语的子序列出现, 就会造成 1 的伤害
而咒语的总伤害为所有 'a'... 'i' 的排列造成的伤害值之和,托米能打出多少点的伤害,是否能击败 1317 呢?
输入描述:
一行输入一个字符串 s
输出描述:
一行输出一个数,表示伤害值
示例1
输入
复制
aabcdefghi
输出
复制
1
备注:
|s| ≤ 3000
题解:求 abcdefghi 的全排列在 S 串中出现的种类数,用 vector 记录每个字母出现的位置(最后一位都是一个比所有位置数大 的 数),在每次全排列后,一次比较对应的位置优先顺序是否符合。
/// AC 代码:
#include<stdio.h>
#include<string.h>
#include<vector>
#include<stdlib.h>
#include<algorithm>
using namespace std;
char s[3005];
vector<int>v[10];
char a[]={'a','b','c','d','e','f','g','h','i'};
int main(){
scanf(" %s",s);
int len=strlen(s);
for(int i=0;i<len;i++){
v[s[i]-'a'].push_back(i);
}
for(int i=0;i<9;i++){
v[i].push_back(len); // 很重要
}
int ans=0;
do{
int leap=0,h=0;
for(int i=0;i<9;i++){ 用二分比较快
h=*lower_bound(v[a[i]-'a'].begin(),v[a[i]-'a'].end(),h);
if(h==len){
leap=1;
break;
}
}
if(!leap)
ans++;
}while(next_permutation(a,a+9));
printf("%d\n",ans);
return 0;
}
/ 超时代吗:
#include<stdio.h>
#include<string.h>
#include<vector>
#include<stdlib.h>
#include<algorithm>
using namespace std;
char s[3005];
vector<int>v[10];
char a[]={'a','b','c','d','e','f','g','h','i'};
int main(){
scanf(" %s",s);
int len=strlen(s);
for(int i=0;i<len;i++){
v[s[i]-'a'].push_back(i);
}
int ans=0;
do{
int flag=0;
for(int i=1;i<9;i++){
int k=i-1;
int leap=0;
for(int j=0;j<v[a[i]-'a'].size();j++){
int leap1=0;
for(int l=0;l<v[a[k]-'a'].size();l++){
if(v[a[i]-'a'][j]>v[a[k]-'a'][l]){
leap1=1;
break;
}
}
if(leap1){
leap=1;
break;
}
}
if(!leap){
flag=1;
break;
}
}
if(!flag)
ans++;
}while(next_permutation(a,a+9));
printf("%d\n",ans);
return 0;
}