今天考了一场小测试,额,非常非常水,但是智障的我才A掉两道题。
T1:
1.暑假作业
(mtime.pas/c/cpp)
【问题描述】
暑假作业是必须要写的,越到假期结束前,写作业的效率就越高,小x就面临这个问题。
现在小x有n个作业要完成。(1 <= N <= 1,000)并且每个作业有两个属性:Ti和Si.Ti表示第i项作业需要Ti的时间来完成,Si表示最迟必须Si时刻完成第i项作业。
现在假设开始时刻为0,而小x想知道最晚什么时候开始写作业,可以把作业完成,这样他可以知道自己可以浮躁的时间。
【输入】
第一行一个整数 N。
接下来N行,每行两个整数T_i (1 <= T_i <= 1,000)和 S_i(1 <= S_i <= 1,000,000)。
【输出】
一个整数,表示小x最晚开始写作业的时刻,如果根本完成不了,输出-1.
【输入输出样例】
mtime.in |
mtime.out |
4 3 5 8 14 5 20 1 16 |
2 |
小x最晚2时刻开始工作,在5时刻完成第一个作业,之后,在14时刻完成第2项作业,在15时刻完成第4项作业,之后在20时刻完成第3项作业。
【数据范围】
30% n<=100
50% n<=500
100% 如 题目描述
非常水的一道题,贪心,然后模拟加时间,看看能不能完成所有作业(并不知道老师为什么出的是暑假作业)。已完成时间为贪心的对象。
#include<iostream> #include<cstdio> #include<algorithm> #include<ctime> #include<cmath> #include<cstring> #include<utility> using namespace std; struct hehe { int ok_time; int need_time; }; hehe a[1050]; int ans=0; int n; bool mycmp(hehe x,hehe y){return x.ok_time<y.ok_time;} int main() { freopen("mtime.in","r",stdin); freopen("mtime.out","w",stdout); cin>>n; for(int i=1;i<=n;i++) { cin>>a[i].need_time>>a[i].ok_time; } sort(a,a+n+1,mycmp); ans=a[1].ok_time-a[1].need_time; int now_time=a[1].ok_time; for(int i=2;i<=n;i++) { if(ans<0) { cout<<"-1"<<endl; return 0; } now_time+=a[i].need_time; if(now_time>a[i].ok_time) { ans-=now_time-a[i].ok_time; now_time=a[i].ok_time; } } cout<<ans<<endl; fclose(stdin);fclose(stdout); return 0; }
T2:
1.福星
(pathhead.pas/c/cpp)
【问题描述】
小x的数学兼体育老师发明了一个很无聊的游戏。
在体育课上,让小x和他的同学们一共N (1 <= N <= 100,000)个人,每个人抽取一个幸运号码A_i (1 <= A_i <= 1,000,000)。
如果第i个人的幸运号码能被第j个人的幸运号码整除,那么第j个人就是第i个人的福星。自己当然不能是自己的福星。
现在小x的数学兼体育老师想让小x算出,每个人都有多少个福星。
【输入】
第一行一个整数N。
接下来N行,每行一个整数A_i,表示每个人的幸运号码
【输出】
N行,每行一个整数,表示每个人的福星个数。
【输入输出样例】
pathhead.in |
pathhead.out |
5 2 1 2 3 4 |
2 0 2 1 3 |
【数据范围】
一共有13组数据
4组数据 n<=100 A_i<=200
6组数据 n<=5000 A_i <=50000
其余如题目描述
额,这道题我刚开始想的是记忆化搜索,然后发现记忆化不行,会出问题,然后就想到了分解因数,就是把人手里的数字分解了,把他所有的因数都存下来。这样的话之前我们要开一个数组记录输入时每个数字出现了几次,然后从因数中找,医药输入时有这个数就证明有一个他的幸运星。算了一下复杂度,极限数据是1*10^8。(但是还是被老师的数据给卡掉了三组数据>_<)
正解是用筛法的思想来写,其实说白了我就得是记忆化搜索的反向。记忆化搜索的是在向后搜索的过程中把前面已经搜索过的只直接调用,但是在这道题中有一个缺陷,就是无法确定这个点的记忆化是前面的哪个点。而用筛法的话可以完整的把后面的点在前面的记忆化个附到后面,举个例子:12 3 2 1输出应该是3 0 1 0用记忆化的话12是无法把2和3都调用的,但是筛法的话就把2和3的只直接附给了12,不会有漏掉的。
额,这里的代码是我的方法,不是筛法(没时间写筛法了,要不写完在写博客估计就回不了家了)
/*#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<ctime> #include<cstring> using namespace std; struct hehe { int num; int ans; int site; }; hehe a[100100]; int n; bool mycmp(hehe x,hehe y){return x.num<y.num;} bool mycmb(hehe x,hehe y){return x.site<y.site;} int main() { freopen("pathhead.in","r",stdin); freopen("pathhead.out","w",stdout); memset(a,0,sizeof(a)); cin>>n; for(int i=1;i<=n;i++) { cin>>a[i].num; a[i].site=i; } sort(a+1,a+n+1,mycmp); a[1].ans=0; for(int i=2;i<=n;i++) { for(int j=i-1;j>=1;j--) { if(a[i].num%a[j].num==0) { a[i].ans=a[j].ans; a[i].ans++; if(a[i].num==a[j].num) a[j].ans++; break; } } } sort(a+1,a+n+1,mycmb); for(int i=1;i<=n;i++) cout<<a[i].ans<<endl; fclose(stdin);fclose(stdout); return 0; } */ #include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<ctime> #include<utility> #include<cstring> //这道题我也是有两个智障的地方,这个库刚开始忘加了。 using namespace std; int sum[1000100]; struct hehe { int num; int site; int ans; }; hehe a[101000]; //这是第二次智障的地方,我把数据量看成10000了。 int n; int q[500],q_q=0; bool mycmp(hehe x,hehe y){return x.num<y.num;} bool mycmb(hehe x,hehe y){return x.site<y.site;} int main() { freopen("pathhead.in","r",stdin); freopen("pathhead.out","w",stdout); cin>>n; for(int i=1;i<=n;i++) { cin>>a[i].num; sum[a[i].num]++; a[i].site=i; } sort(a+1,a+n+1,mycmp); for(int i=1;i<=n;i++) { int k=a[i].num; for(int j=1;j<=sqrt(k*1.0);j++) { if(k%j==0) { q[++q_q]=j; if(k/j!=j) q[++q_q]=k/j; } } for(int j=1;j<=q_q;j++) { a[i].ans+=sum[q[j]]; } a[i].ans--; q_q=0; } sort(a+1,a+n+1,mycmb); for(int i=1;i<=n;i++) cout<<a[i].ans<<endl; fclose(stdin);fclose(stdout); return 0; }
T3:
1.字符游戏
(moo.pas/c/cpp)
【问题描述】
小x和同学们喜欢玩一种游戏叫 "Moo".
他们总是站在一排,然后依次说出相应的一个字符,如果出错的同学,就要受到惩罚。
下面就是这个游戏的一个序列:
m o o m o o o m o o 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 o m o o"
S(2) = "m o o m o o o m 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以内。
哈哈哈,老师偷懒把usaco2017年1月的月赛银组题的T3用了,虽然说有点改变但是还是很简单的,就找一下规律就好了。我们发现这道题每次进行改变以后他的长度是有规律可循的,这样的话我们就很简单的想到了递归的思想来写。我们要根据他给的x,来判断x在前面一次变换中的位置,但是有一次特判,就是把如果这个x落到了想moo,mooo,mooooo......这种情况的话我们就可以直接进行输出,如果是第一个的话直接输出‘m’,其他情况就是‘o’。
#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #include<cstring> #include<utility> #include<ctime> using namespace std; long long a[30]; //智障的我刚开始把a就开了20个,直接导致了就过了三组数据。 long long n; int m; string s="moo"; int main() { freopen("moo.in","r",stdin); freopen("moo.out","w",stdout); cin>>m; a[1]=3; for(int i=2;i<=29;i++) a[i]=a[i-1]*2+3+i-1; for(int i=1;i<=m;i++) { cin>>n; int k; bool flag=0; for(int j=1;j<=29;j++) { if(n>a[j] && n<=a[j+1]) { k=j; break; } } while(n>3) { if(n>=a[k]+1 && n<=a[k]+k+3) { if(n==a[k]+1) cout<<'m'<<endl; else cout<<'o'<<endl; flag=1; break; } else { n-=(a[k]+3+k); } while(n<=a[k]) k--; } if(!flag) cout<<s[n-1]<<endl; } fclose(stdin);fclose(stdout); return 0; }
T4:(这题好难,真的不会,然而网上有别的题解,但是和我的思想不一样)
骰子游戏 pogo
题目描述:
小x在玩一个骰子游戏。
这个骰子有6个面,如图所示:相对的两个面的值的累加和是7,数字1相对的面是数字6,2对着5,3对着4.
现在,有一个r行,c列的表格,骰子在表格最左上角,数字1朝上,数字3在1的右边。
现在小x按照以下规则进行移动:
1:他先把骰子从第一行的第一列,向右依次滚到最右边那列。
2:他把骰子向下滚到下一行。
3:他把骰子从右依次滚到最左边那列。
4:依次类推,他又把骰子滚到下一行,并按照第一步那样依次滚动
小x依次的重复以上步骤,直到把所有的格子都滚一遍。
在滚到每个格子的时候,小x都会记录朝上那面的格子的数字。
现在小x要考验一下你,所有数字的和是多少?
输入格式:
两个用空格隔开的整数r和c(1 ≤ r,c ≤ 100 000), 表示题目描述的表格的行和列。
输出格式:
一个整数,如题目描述的所有朝上那面数字的累加和。
样例1:输入 |
样例2:输入 |
样例3:输入 |
3 2 |
3 4 |
737 296 |
样例1:输出 |
样例2:输出 |
样例3:输出 |
19 |
42 |
763532 |
50%数据保证 r和c小于等于100
这道题很明显可以发现要模拟,网上有别人的模拟找到了规律,然而我的模拟是一行一行的模拟,首相真一行要ans+=(c/4)*14,然后在把剩下的加进去,开一个变量表示方向(正着滚还是反着滚),然后输出答案就好了。
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<string> #include<iomanip> #include<cmath> using namespace std; int a,b,c,shang=1,zheng=2,you=3,fang=1; long long sum=0; int main() { freopen("pogo.in","r",stdin); freopen("pogo.out","w",stdout); cin>>a>>b; for(int i=1;i<=a;i++) { sum+=shang; sum+=((b-1)/4*14); for(int j=1;j<=(b-1)%4;j++) { if(fang==1) { int qw=you; you=shang; shang=(7-qw); sum+=shang; } else { int r=shang; shang=you; you=(7-r); sum+=shang; } } if(fang==1) fang=2; else fang=1; int w=zheng; zheng=shang; shang=7-w; } cout<<sum<<endl; return 0; }
最后再多说几句,这道题还是很简单的,本来以为要ak的,还是太年轻了,有点粗心了,看错了两个数据范围,库还忘加了一个,但是也不是很可惜,因为本来就ak不了,第二题被卡了三组数据。