1.采蘑菇的拖拉机
【问题描述】
春天来了,朱昶成的农场里会长很多蘑菇,而观察奶牛开着拖拉机采蘑菇成了朱昶成喜爱做的一件事情。
朱昶成的农场被分为了一个平面坐标系,最左下角的坐标为(1,1),最右上角的坐标为(10^5,10^5).
朱昶成有一个探测蘑菇的雷达,当开启蘑菇雷达后,这个雷达每一秒会发现农场上的一个蘑菇,并且会告知这个蘑菇的坐标。
朱昶成的奶牛只会沿着一个方向开拖拉机,并且不会拐弯,这里的方向指的是和坐标轴平行的四个方向和与坐标轴夹角45度的对角线(当然是两条对角线)。并且每天朱昶成只允许奶牛开一次拖拉机,也就是说,每次采蘑菇,拖拉机只能沿着一个方向去采集所经过的点的蘑菇。
朱昶成允许他的奶牛从农场里的任意一个点,任意一个方向出发,并且他的拖拉机的速度奇快,从启动到完成任务话费的时间忽略不计。现在朱昶成想直到,如果要一次性的采集K个蘑菇,最早在什么时间完成任务。
【输入】
为了防止骗分,测试数据为两组,每一组数据格式如下:
第一行两个整数N和K。表示有N个蘑菇出现,朱昶成要采集K个蘑菇。
接下来N行,第i行为两个整数Xi和Yi,表示第i秒发现的蘑菇的坐标为Xi和Yi。
在某一个坐标陆续发现多个蘑菇的可能性也是有的。
【输出】
两行,每行一个整数T,表示最早第T秒就可以完成K个蘑菇的采集。如果无法满足要求,那么这行输出-1.
【输入输出样例1】
tractor.in
tractor.out
4 3
1 2
3 4
3 2
4 5
5 2
1 1
2 1
1 2
1 3
1 4
4
2
第四秒开始,可以采集第1,2,4个蘑菇。
【数据范围】
50% 数据保证Xi,Yi在[1..300]之间
100% 数据保证N在[2..10^6]之间, K在[2..N]之间。Xi和Yi在[1..10^5]之间。
题目述概:
也就是题目分两组数据,每次给你一个坐标,每次判断坐标的行,列和45°角,然后那个先到达规定值就输出那个
题目思路:
1.判断行:很简单,用一个数组存储即可
2.判断列:同上
3.判断45°角:需要补充一下知识点:每条45°角的行列之和或之差都相
图一
如图一:每条45°角,即红线的行列之和都相等
图二
如图二:换一个方向的每条45°红线的行列之差相等
但是因为会有负数,再加上100000就好了
代码
#include<bits/stdc++.h> using namespace std; int main() { int a[1100000]={},b[1100000]={},c[1100000]={},d[2100000]={}; int n,k,x,y,t=0; cin>>n>>k; for (int i=1;i<=n;i++) { cin>>x>>y; a[x]++;//行 b[y]++;//列 c[x+y]++;//正45° d[x-y+100000]++;//反45° if (a[x]==k||b[y]==k||c[x+y]==k||d[x-y+100000]==k) { t++; if (t==1) cout<<i<<endl; } } cin>>n>>k;t=0; memset(a,0,sizeof(a)); memset(b,0,sizeof(b)); memset(c,0,sizeof(c)); memset(d,0,sizeof(d)); for (int i=1;i<=n;i++) { cin>>x>>y; a[x]++; b[y]++; c[x+y]++; d[x-y+100000]++; if (a[x]==k||b[y]==k||c[x+y]==k||d[x-y+100000]==k) { t++; if (t==1) cout<<i; } } return 0;2.加密工作
【问题描述】
2027年,从清华毕业的久知找了一份为一些文件的某些部分加密的工作,加密的部分是一串小写英文字母,加密的规则是这样的:要是连续出现相同的字母,则把他们替换成这个字母的大写形式,后面紧跟相同字母的个数,并把它之前跟之后的两端字符串调换,例如出现bcmatchingaef,则字符串变成:efA6bc。然后重新扫描字符串,直到没有出现相同小写字母为止。
【输入】
原始字符串(长度不大于250)。
【输出】
新的字符串。
【输入输出样例1】
password.in
password.out
bcmatchingaef
efA6bc
【输入输出样例2】
password.in
password.out
cmmmcefffg
gM3cF3ce
样例2解释:cM3cefffg——cefffgM3c——ceF3gM3c——gM3cF3ce
思路:题目不难,主要是运用一个substr函数,并考虑二位数的情况#include<bits/stdc++.h> using namespace std; int main() { string s; int k=1,i,j,ans; cin>>s; while (k) { k=0; for (i=0;i<s.size();i++) if (s[i]==s[i+1]) { ans=1; for (j=i+1;j<s.size();j++) if (s[j]==s[i]) ans++; else break; if (ans>=10) s=s.substr(j,s.size()-j)+char(s[i]-32)+char(ans/10+48)+char(ans%10+48)+s.substr(0,i); else s=s.substr(j,s.size()-j)+char(s[i]-32)+char(ans+48)+s.substr(0,i); k=1; break; } } cout<<s; return 0; }
3.小顾的字符游戏
【问题描述】
小顾和同学们喜欢玩一种游戏叫 "Moo".
他们总是站在一排,然后依次说出相应的一个字符,如果出错的同学,就要受到惩罚。
下面就是这个游戏的一个序列:
m o o m o o o m oo m o o o o m o o m o o o m o o m o o o o o
这个游戏的序列最初状态是 S(0) "m o o",也就是初始状态只有3个字符;如果要查询的字符超过3个,就要产生下一个字符序列,产生序列的规则如下:
s(k)是 s(k-1) + "m o ... o"(k+2)个'o' +s(k-1)
下面是相应的序列
S(0) = "m o o"
S(1) = "m o o m o o om o o"
S(2) = "m o o m o o om o o m o o o o m o o m o o o m o o"
注意:如果游戏的序列长度不够,就按照以上规则继续往下产生就可以了,所以游戏用的序列是无穷大的。
那么现在问题就出来了:
游戏中第x个人需要说的字符是什么呢?当然只有可能是 'm'或'o'.
本题有m(m<=10)个提问,每个提问给一个整数x,你要回答第x个人需要说出的字符数。
【输入】
第一行一个整数m(m<=10)
接下来m行,每行一个整数x (1 <=x<= 10^9)
【输出】
m行,每行一个字符,第i个人需要说的字符。
【输入输出样例1】
moo.in
moo.out
2
1
11
m
m
【数据范围】
如题目描述。保证会有部分小数据查询位置在200以内。
大致思路:不难发现,每一组数据分成三段,两段和s(i-1)相同,另一段式m加上很多个o组成,然后只要用一个数组存储每一组数据的中间的两个交接点,然后用递归的方式去查找:如果查找的数字为s(0)的范围内,则直接输出;如果超范围了,则继续递归,如果递归在第一个点和第二个点之内,直接输出也很方便;但是在第二个点的范围之外,则递归s(i-1),知道递归到s(0)。
#include <bits/stdc++.h> using namespace std; struct moo { long long len,dian1,dian2; } a[40]={};//用结构体存储点一个点,第二个点,和长度 void find(int x) { if (x==1){cout<<'m'<<endl;return;} if (x==2||x==3){cout<<'o'<<endl;return;}//如果范围在s(0) for (int i=1;i<=30;i++) { if (x>a[i].len)continue;//如何超范围 if (x==a[i].dian1){cout<<'m'<<endl;return;} if (x>a[i].dian1&&x<a[i].dian2){cout<<'o'<<endl;return;}//如果在点一个点之后和在第二个点之前 if (x>=a[i].dian2){find(x-a[i].dian2+1);return;}//递归s(i-1) } } int main() { a[0].len=3; a[0].dian1=a[0].dian2=0; for (int i=1;i<=30;i++) { a[i].len=a[i-1].len*2+i+3; a[i].dian1=a[i-1].len+1; a[i].dian2=a[i-1].len+i+4; } int n; cin>>n; for (int i=1;i<=n;i++) { int k; cin>>k; find(k); } return 0; }//主体部分就不说了,自己看吧