2017.10.16队内互测——胡策
来源:互联网 发布:跨平台app开发 知乎 编辑:程序博客网 时间:2024/05/22 00:48
出题人:Byike,RC,lxt ,Q
本套题死宅气息浓厚…
Problem 1 :埃罗芒阿老师
题目来源:http://codevs.cn/problem/2913/
题目描述
埃罗芒阿老师是著名的插画家, 她的工作是为
电击文库出版的的书画插画。快要到截稿日了,埃罗芒阿老师还在水>_<埃罗芒阿突然发现自己还有一大堆插画没有完成,如果不能在截稿时间内完成是要扣工资的。
于是埃罗芒阿老师把每个任务所需的时间和现在(0 时刻)距离每个任务截稿的时间记录了下来,想要计算出最多可以完成多少任务。
输入描述
第一行是一个整数 N,接下来 N 行每行两个整数 T1,T2 描述一个任务: 完成这个任务需要 T1 秒,如果在 T2 秒之内还没有完成任务,这个任务就到截稿时间了。
输出描述
输出一个整数 S,表示最多可以完成 S 个任务.
样例输入
4
100 200
200 1300
1000 1250
2000 3200
样例输出
3
数据范围及提示
对于 30%的数据, N≤100;
对于 60%的数据, N≤10000;
对于 80%的数据, N < 150,000; T1 < T2 <
INT_MAX;
对于 100%的数据, N < 150,000; T1 < T2 <
LLONG_MAX;
所有数据保证随机生成。
思路
按照截稿日期从小到大排序,截稿日期相同则按耗费时间从小到大排序。记录当前选取任务的总时间sum,每次对于一个任务,若由sum结束时间到截稿时间间允许完成这项任务则直接加入答案,若不能则取出已选择任务中耗费时间最多的任务,如果其耗费时间大于当前任务则与之交换,即选择当前的而放弃耗费时间最大的,这里用堆来维护。
贪心策略:尽量使得后面任务的剩余时间多,可证
代码
#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<cmath>#include<queue>using namespace std;int n;unsigned long long sum,ans;struct ren{ unsigned long long s,t; bool operator < (ren a)const { return s<a.s; }}l[200010];priority_queue<ren>q;bool cmp(ren a,ren b){ return a.t==b.t?a.s<b.s:a.t<b.t;//写法}int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%I64d%I64d",&l[i].s,&l[i].t); sort(l+1,l+n+1,cmp); for(int i=1;i<=n;i++) { if(l[i].t-sum>=l[i].s) { q.push((ren){l[i].s,l[i].t}); sum+=l[i].s; ans++; } else { ren k=q.top(); if(k.s>l[i].s)//不会使后面剩余空间变小 { //不可以写为if(l[i].t-(sum-k.s)>l[i].s),有可能会使后面剩余空间变小 q.pop(); q.push((ren){l[i].s,l[i].t}); sum-=k.s; sum+=l[i].s; } } } printf("%I64d",ans); return 0;}
Problem 2 :名侦探柯南
题目来源:http://codevs.cn/problem/1089/
题目描述
铃木次吉郎又一次向基德发出挑战,而这次的挑战是在铃木号快车上,这辆一年只运行一次的快车上,乘客几乎是固定不变的,尤其是 7 号车厢,这节车厢里的乘客每年都提前预定,而这么做的理由也只是为了参加在这辆车上独有的推理谜题,不幸的是,因为今年毛利小五郎的出现,在这节车厢中出现真的杀人事件,现在为了找出凶手,车厢中的人被聚集到一起,共有 N 个人,他们一共会说 P 句证词,但N 个人中会有 M 个人说谎, 但凶手只有一个,因为柯南还在寻找其他证据,为此你要通过他们说的话去判断凶手是谁。
输入描述
输入第一行为 3 个数, N,M,P,分别表示有 N 个人, M 个人说谎, P 句证词以下 N 行,每行一个人名(全部大写)之后 P 行,每行开始为一个人名,后紧跟一个冒号和一个空格,后面是一句证词(符合表中所列的格式,可能有废话)证词每行不超过 250 个字符输入中不会出现连续的两个空格,且每行开头和结尾也没有空格。
单词注明: guilty
角色注明:
铃木次吉郎:铃木财团顾问, 爱好环游世界,在得知有关基德的事
件后, 扬言要亲手逮捕基德(用自家的宝石来作为诱饵)
基德(KID):本名黑羽快斗,为调查父亲死亡真相而成为怪盗寻找
珍稀的宝石, 以此找出幕后真相, 也以铃木拿宝石挑战作契机寻找
宝石(详情请见怪盗基德 1412)
江户川柯南:原名工藤新一(滚筒洗衣机), 在服用酒厂药物后变小
而以柯南为名掩盖自己未死的真相
毛利小五郎:一直划水的侦探
输出描述
输出只有一行, 有三种情况:
1 , 若确定一个凶手,则输出凶手名字
2 , 找到符合条件的凶手, 但有多个,输出
“Cannot Determine” (不含引号)
3 , 没有找到符合条件的凶手, 即根据已知条件不能
确定任何一个可能的凶手,输出“Impossible” (不
含引号)。
样例输入
3 1 5
MIKE
CHARLES
KATE
MIKE: I am guilty.MIKE: Today is Sunday.
CHARLES: MIKE is guilty.
KATE: I am guilty.
KATE: How are you??
样例输出
MIKE
数据范围及提示
1<=N<=20 , 0<=M<=N ,1<=P<=100
数据保证不随机生成。
凶手保证在 N 个人中,但他/她不一定说过话。
思路
枚举犯人枚举今天是星期几,若合法则更新答案,但实现实在是恶心…代码能力题
代码
#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<cmath>#include<map>using namespace std;int n,m,p,t,f,ans;int tf[1010];string s,now;string num[1010];struct inf{ int id;//说话者的编号 string sy;//证词 }fl[1010];map<string,int>name;//将人名映射到编号 const string days[]={ "Today is Monday.", "Today is Tuesday.", "Today is Wednesday.", "Today is Thursday.", "Today is Friday.", "Today is Saturday.", "Today is Sunday.",};bool check(int a,int b){ if(tf[a]==-1) { if(!b) f++; else t++; if(f>m)//超过给定人数不合法 return 1; if((n-t)<m)//同理 return 1; } if(tf[a]==-1) { tf[a]=b;//记录 return 0; } else { if(tf[a]==b) return 0; else return 1;//与之前的情况冲突 } }void solve(int k,string day){ memset(tf,-1,sizeof(tf));//记录每人说的是真话1还是假话0 t=f=0;//t为未说谎的人数,f为说谎的人数 for(int i=1;i<=p;i++) { int pos; pos=fl[i].sy.find("I am guilty."); if(~pos)//pos!=EOF但不可以写为pos!=0 { if(check(fl[i].id,fl[i].id==k)) return;//当前状态不合法便退出 } pos=fl[i].sy.find("I am not guilty."); if(~pos) { if(check(fl[i].id,fl[i].id!=k)) return; } pos=fl[i].sy.find(" is guilty."); if(~pos) { now=fl[i].sy; now.erase(pos,11); int b=name[now]; if(check(fl[i].id,b==k)) return; } pos=fl[i].sy.find(" is not guilty."); if(~pos) { now=fl[i].sy; now.erase(pos,15); int b=name[now]; if(check(fl[i].id,b!=k)) return; } pos=fl[i].sy.find("Today is "); if(~pos) { if(check(fl[i].id,fl[i].sy==day)) return; } } if(ans&&ans!=k) { printf("Cannot Determine"); exit(0);//终止程序 } ans=k;}int main(){ scanf("%d%d%d",&n,&m,&p); for(int i=1;i<=n;i++) { cin>>num[i]; name[num[i]]=i; } for(int i=1;i<=p;i++) { cin>>s; s.erase(s.length()-1,1);//删除':' fl[i].id=name[s]; getline(cin,fl[i].sy); fl[i].sy.erase(0,1); } for(int i=1;i<=n;i++)//枚举犯人 for(int j=0;j<=6;j++)//枚举今天是星期几 solve(i,days[j]); if(!ans) printf("Impossible"); else cout<<num[ans]; return 0;}
Problem 3 :
题目来源:https://www.luogu.org/problem/show?pid=2246#sub
题目描述
一天, 翻阅 Dark Flame Master 黑暗笔记的邪王真眼使发现了笔记中所记载的不可視境界線的秘密。在黑暗笔记的某一页, 她看见了一篇文章。 这篇文章里记载着寻找不可視境界線并前往异世界的方法。
这篇文章由英文字母、和空白字符(制表/空格/回车)构成,但由于管理局的介入,字母的大小写变得十分混乱,换行和空格也不成章法。
Dark Flame Master 告诉邪王真眼使,这篇文章中其实隐含着一个数字 x,只要朝向不可視境界線并说出 x 次“闇の炎に抱かれて消えろっ! ”就可以打开异世界的通道, 这个 x 就是”HelloWorld” 在文章中作为子序列出现的次数。
于是邪王真眼使重新阅读了笔记并解放了“じゃおう シンガン” 的力量!
由于解放后的“じゃおう シンガン” 力量十分强大, 所以大小写对于她而言毫无区别;因此, “hEllOWorLD” 这样的子序列是可以的。 所有的空格回车和制表符都可以被她直接忽略掉;也就是说,“HelloWorld” 是可以的; 当然, “hE Llow oR ld” 也是可以的。
现在,借助邪王真眼使的力量, Dark Flame Master 需要帮助她计算出在这篇文章中“HelloWorld” 作为子序列出现的次数。由于答案可能很大, 请输出结果对 1000000007(10^9+7)的余数。
输入描述 输入包含若干行。这些行的内容共同构成一篇文章(由于管理局的介入, 十分可能出现语法不通顺的情况) 。文章以 EOF(文件结尾)结束。
输出描述 输出仅包含一个整数,表示这篇文章中“HelloWorld” 出现的次数。
样例输入
1
HhEeLlLlOoWwOoRrLlDd
样例输出
1
1536
样例输入
2
Gou Li Guo Jia Sheng Si Yi
Qi Yin Huo Fu Bi Qu Zhi
River can feed people
Also can race boats
Hall Ellen Ok Words locked
样例输出
2
273
数据范围及提示
记 n 为输入的文章的长度(字符数)。
对于 20%的数据, n <= 20。
对于 50%的数据, n <= 500。
对于所有的数据, 15 <= n <= 500000。
数据不保证随机生成。 (╯▽╰)
被漆黑烈焰吞噬殆尽吧!
思路
简单处理一下输入,方法 1:设置DP数组f[i][j]表示字符串匹配到i位置,HELLOWORLD(模板串)匹配到j位置的方案数。将无关字母忽略,对于只存在模板串中字母的情况,转移为:
f[i][j]=f[i-1][j];
if(s[i]==t[j])
f[i][j]+=f[i-1][j-1];
代码
#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<cmath>using namespace std;const int mod = 1000000007;int len;int f[500010][15];string s,t;int main(){ s+="*";//或者为'*',使string储存开始下标为1 while(cin>>t)//与scanf写法不同 s+=t;//string的方便之处 t="*HELLOWORLD"; len=s.length()-1; for(int i=1;i<=len;i++) if(s[i]>='a')//转换为大写字母 s[i]-=32; for(int i=0;i<=len;i++) f[i][0]=1;//初始化为1,使得在之后的更新中可以加上字母本身长度1数量 for(int i=1;i<=len;i++)//二维,i-1状态的所以情况都已确定 for(int j=1;j<=10;j++) { f[i][j]=f[i-1][j];//字符串匹配到i的位置,HELLOWORLD匹配到其中j的位置的方案数首先等于前一位置匹配到j位置的方案数 if(s[i]==t[j])//若当前位置i可以与j位置匹配,确定位置并过滤无关字符 f[i][j]+=f[i-1][j-1],f[i][j]%=mod;//乘法原理,每一个原串位置在i之前,模板串位置在j之前的字母都会与当前字母形成一个新的方案,累加答案 //不可直接写作%=1e9+7,类型为double无法与int取模 } printf("%d",f[len][10]); return 0;}
方法 2:设置DP数组f[i]表示以i号位置字母(模板串)结尾的子序列的方案数,由于少了一维,我们无法通过前一维找到可用来转移的前一状态,于是对i倒序枚举,使得以i位字母在原串位置之前的所有字母结尾的方案数都已求出后才更新i位,保证由前向后转移
转移时,对于f[i],在之前的串中出现时更新的方案数作为这一次的基数,然后再加上以前一位字母(模板串)结尾的子序列方案数即:
f[i]=f[i]+f[i-1];
原理:f[i-1]包含了f[1~i-1]的答案
#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<cmath>using namespace std;const int mod = 1000000007;char ch;int f[1010];int main(){ char t[12]="*helloworld";//11太小..好像应该空出1位来 f[0]=1;//初始化 while((ch=getchar())!=EOF)//不可写作~ch=getchar(),注意(ch=getchar())加括号... { for(int i=10;i>=1;i--)//倒序枚举 { if(ch==t[i]||ch+32==t[i])//f[i-1]包含有结尾字母位置为1-i-1的子序列的方案数 f[i]=(f[i]+f[i-1])%mod;//以i位置字母结尾的子序列的方案数=之前已有的方案数+以i-1位置字母结尾的子序列的方案数 } } printf("%d",f[10]); return 0;}
Problem 4 :
题目来源:https://www.luogu.org/problem/show?pid=3927
题目描述
银桑、神乐、新八三人在测试阿姆斯特朗回旋加速喷气式阿姆斯特朗炮的威力。
阿姆斯特朗回旋加速喷气式阿姆斯特朗炮十分神奇, 使用方式如下:
输入两个数字 n,k 到阿姆斯特朗回旋加速喷气式阿姆斯特朗炮的控制台中,然后阿姆斯特朗回旋加速喷气式阿姆斯特朗炮会计算出 n!并把它转化为 k 进制。最后 n!在 k 进制下末尾 0 的个数就是本次发射的威力,每个 0 代表 1 点威力。
为了测试时不造成太大的破坏,三人想知道每次测试,发射的威力有多大。
现在给出多组测试的 n 和 k, 请计算出每次发射的威力。
输入描述
输入文件为 amstl.in
题目包含多组数据, 以 EOF(文件结尾)为结束。所有题目数据保证不包含样例。
long long 类型输入输出请用%I64d。
对于每组数据,输入一行两个正整数 n,k;
输出描述
输出文件为 amstl.out
每组数据一行,包含一个整数,表示本次发射的威力。
样例输入
10 40
样例输出
2
数据范围及提示
对于 30%的数据, n <= 1000000, k = 10
对于另外 10%的数据, n <= 20, k <= 20
对于另外 20%的数据, n <= 50, k <= 52
对于另外 10%的数据, n<=10^12, k = 2
对于 100%的数据, n <= 10^12, k <= 10^12
思路
对于一个数转k进制数,在前数%k==0时(%后前数/k)使得末尾0的个数加一。
于是考虑对n!和k进行质因数分解,对n!进行质因数分解即对1~n中的数进行质因数分解——原理同之前的高校模拟赛:赛小城学数学 http://blog.csdn.net/qq_36693533/article/details/78218929
则答案为k的某一质因子(在1-n中的出现次数/在k中的出现次数)的最小值,即为k被n!整除的次数
代码
#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<cmath>using namespace std;typedef long long ll;ll n,ns,k,cnt1,cnt2,ans;int main(){ while(~scanf("%lld%lld",&n,&k)) { ans=1e17+7; for(int i=2;i<=sqrt(k)+1;i++)//至多不大于根号n { ns=n;//注意n的值不可以随着循环改变 cnt1=0; cnt2=0; while(k%i==0) cnt1++,k/=i; if(cnt1) { ll base=i; while(ns) cnt2+=(ns/base),ns/=base;//ns/base:1~ns中包含有base这个质因子的数的个数 ans=min(ans,cnt2/cnt1);//将k中某一质因子的个数在n中的倍数取min } } if(k>1)//当前k为一质因子 { cnt2=0; while(n) cnt2+=(n/k),n/=k; ans=min(ans,cnt2); } if(ans==1e17+7) ans=0; printf("%lld\n",ans); } return 0;}
- 2017.10.16队内互测——胡策
- 2017.10.16 队内互测 D4
- 2017.10.10队内互测——高校模拟赛
- 2017.10.12队内互测——新一波高能胡策题
- 2017.10.18队内互测——一场简单的模拟赛
- 2017.10.22队内互测——Loi水题汇总
- 2017.10.24队内互测——压轴出场的互测终曲|(*_-)
- 2017.9.16队内互测——老年组Day1
- 2017.10.16
- 2017.10.16
- 每日杂谈 -- 2017.10.16
- 2017.10.16学习
- Test 2017.10.16
- 2017.10.16总结
- Test 2017.10.16
- 【队内胡策】2017.10.16
- 2017.10.16一试
- 16——3
- 如何在linux(ubuntu)下安装source insight
- 2.4电子音乐与MIDI
- Advanced Programming in UNIX Environment Episode 10
- java接口中的变量
- 千里之行,始于足下。动起来
- 2017.10.16队内互测——胡策
- 消息对话框:alert、confirm、prompt
- 三目运算符
- Android 自定义线程池
- 释放资源
- unity优化《三》--将包大小减少到极致
- 前端实现下拉显示更多功能
- 使用Lint工具进行代码分析
- Linux内核中内存管理相关的数据结构