江西财经大学第一届程序设计竞赛

A 贪玩蓝月

题目描述

"挤需体验五番钟,里造会挨上这款游戏!"
怎么可能嘛!当我是傻子吗!#?%!“”@……
于是我就去玩了,然后我果然成功证明,我是正确的,这破游戏,真的很无聊.
有多无聊呢,和这道题一样.
------------------------------------
问题有两种情况
0 给出两个100以内的正整数做加法
1 给出一个字符串问有多少个字符(字符串长度不超过100000)

输入描述:

第一行输入一个整数T(表示样例个数)
接下来T组样例
每组样例先输入一个整数N(0或者1)
若N为0,则输入两个整数a,b(0<=a,b<=100)
若N为1,则输入一个字符串s

输出描述:

输出T行
每行输出一个样例对应的结果
示例1

输入

2
0 1 1
1 aa

输出

2
2

签到题
 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <cstring>
 4 using namespace std;
 5 #define ll long long
 6 const int N = 110;
 7 string s;
 8 int main() {
 9     int t, a, b, n;
10     cin >> t;
11     while(t--) {
12         cin >> n;
13         if(n == 0) {
14             cin >> a >> b;
15             cout << a+b<< endl;
16         } else  {
17             cin >> s;
18             cout <<s.length() << endl;
19         }
20     }
21     return 0;
22 }

B 大吉大利

题目描述

给出一个出生日期,比如:1999-09-09,
问:从出生那一天开始起,到今天2018-04-21为止(包括出生日期和今天),有多少天,年月日都不包含数字4?

输入描述:

第一行输入一个整数T(表示样例个数)
接下来T组样例
每个样例一行,包含一个字符串“yyyy-mm-dd”(1990<=yyyy<=2018)
题目保证测试数据的正确性

输出描述:

输出题意要求的天数
示例1

输入

1
1999-09-09

输出

5020

从y-m-d遍历到2018-04-21,然后计算数量
 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <cstring>
 4 using namespace std;
 5 #define ll long long
 6 const int N = 11;
 7 int day[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
 8 bool ok(int y) {
 9     if((y%4==0&&y%100!=0) || y%400==0) return true;
10     else return false;
11 }
12 bool ok1(int x) {
13     while(x) {
14         if(x%10 == 4) return true;
15         x /= 10;
16     }
17     return false;
18 }
19 int main() {
20     int t, y, m, d;
21     cin >> t;
22     while(t--) {
23         scanf("%d-%d-%d",&y,&m,&d);
24         int ans = 0;
25         if(y == 2018) {
26             for(int i = m; i <= 4; i ++) {
27                 for(int j = 1; j <= day[i]+(i==2&&ok(y)?1:0); j ++) {
28                     if(i == 4 && j == 21) break;
29                     if(ok1(i) || ok1(j)) continue;
30                     ans++;
31                 }
32             }
33         } else {
34             for(int i = m; i <= 12; i ++) {
35                 for(int j = 1; j <= day[i]+(i==2&&ok(y)?1:0); j ++) {
36                     if(i == m && j < d) continue;
37                     if(ok1(y) || ok1(i) || ok1(j)) continue;
38                     ans++;
39                 }
40             }
41             for(int i = y+1; i < 2018; i ++) {
42                 for(int j = 1; j <= 12; j ++) {
43                     for(int k = 1; k <= day[j]+(j==2&&ok(i)?1:0); k ++) {
44                         if(ok1(i) || ok1(j) || ok1(k)) continue;
45                         ans++;
46                     }
47                 }
48             }
49             for(int i = 1; i <= 4; i ++) {
50                 for(int j = 1; j <= day[i]; j ++) {
51                     if(ok1(i) || ok1(j)) continue;
52                     ans++;
53                 }
54             }
55         }
56         printf("%d\n",ans);
57     }
58     return 0;
59 }

C 今晚吃鸡

题目描述

决赛圈还剩下两个人,“伏地魔”XDD和跑毒进圈的FZL,XDD拿着狙击枪AWM瞄准并准备射击奔跑中的FZL。
XDD知道自己只有这一次机会,如果失误了,他就会被大哥FZL空中360度甩狙一枪带走。
那么XDD能吃鸡吗,请你帮助他。
-------------------------------------------
为了便于分析,子弹,XDD,FZL都假设为原点,子弹水平射出,FZL在奔跑过程中与XDD的距离不变。
子弹下坠的加速度为9.8米每秒。
给出 XDD和FZL的距离 浮点数 L 、子弹的速度 浮点数V1、FZL奔跑的速度浮点数 V2
XDD需要知道从射击到击中目标这段时间内 子弹下坠的距离 L1和 FZL跑动的距离L2,从而预判射击的位置,请你帮他计算。

输入描述:

第一行输入一个整数T(表示样例个数)
接下来T组样例
每个样例一行,包括三个浮点数 L V1 V2(0<L,V1,V2<=10000)

输出描述:

输出T行
每个测试用例输出一行对应的结果
L1 L2(一个空格隔开,结果保留6位小数)
示例1

输入

1
100 1000 10

输出

0.049000 1.000000

物理问题,一开始还v1-v2了,其实是相对静止。
 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <cstring>
 4 using namespace std;
 5 #define ll long long
 6 const int N = 11;
 7 int main() {
 8     int t;
 9     cin >> t;
10     while(t--) {
11         double L, v1, v2;
12         cin >> L >> v1 >> v2;
13         double t = L/(v1);
14         printf("%.6lf %.6lf\n",9.8*t*t/2,v2*t);
15     }
16     return 0;
17 }

D SSR

题目描述

事情,是这样的。
有这么一天双休日的中午。
我刚把我衣服扔进了洗衣机,然后拿了个小板凳坐在旁边发呆。
然后突然想到这么无聊干脆玩会阴阳师好了,于是从斗篷帽子里掏出我的手机登录了阴阳师。
看着更新公告里写着的新SSR式神一目连感叹了一下:我要是能有个一目连该多好啊
看了一眼我家帅气的扛把子咕咕,正准备肝困难的时候发现庭院里那一串灯笼里的调查问卷有蝴蝶在绕,于是点进去填了一波在最结尾写上了我当时的愿望:我想要一目连。
然后奖励了一个符,顺手就抽了。本来以为又是R卡,没想到手机震动了一下。
握草!!!一目连!!!!
当时我就激动的站了起来使劲看了一眼然后仰天大笑以及截图装逼。
---------------------------------------------------------------------------------------
SSR全称为superior super rare,特级超稀有。一般为卡牌类游戏最高稀有等级。
 
题目是给出三个字符,求其升级到SSR所需要的次数。
最小为AAA,最大为SSR;
SSQ升级到SSR需要升级1次,
SRR升级到SSR需要升级19次。

输入描述:

第一行输入一个整数T(表示样例个数)
接下来T组样例
每个样例一行,包含三个连续的大写字母(A - S)

输出描述:

每个样例输出一行
升级到SSR所需的次数
示例1

输入

3
SSR
SRR
AAA

输出

0
19
6857

备注:

SRR升级到SSR的过程:
SRR -> SRS -> SSA ->SSB -> SSC -> ……->SSR 共19次

循环,直到等于SSR,然后输出值
 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <cstring>
 4 using namespace std;
 5 #define ll long long
 6 const int N = 11;
 7 char str[N];
 8 int main() {
 9     int t;
10     cin >> t;
11     while(t--) {
12         cin >> str;
13         for(int i = 0; ; i ++) {
14             if(str[0] =='S' && str[1] == 'S' && str[2] == 'R') {
15                 printf("%d\n",i);
16                 break;
17             }
18             if(str[2] == 'S') {
19                 if(str[1] == 'S') {
20                     str[0] += 1;
21                     str[1] = 'A';
22                 } else {
23                     str[1] += 1;
24                 }
25                 str[2] = 'A';
26             } else str[2] += 1;
27         }
28     }
29     return 0;
30 }

E 消息列表

题目描述

当你的好友给你发来一条消息,你的消息列表上就会置顶显示该好友的名字以及该好友发给你的消息总数,换句话说,你的消息列表里的好友是按跟你发消息的时间进行排序的,给你发消息的时间离当前时间越近的好友将排到越前面。当然,你可能会手动置顶一些好友,那么其他的好友给你发消息时,他们的名字就只能在你手动置顶好友的后面再置顶了。如果消息被你查看或者忽略,又或者你把好友消息删除了,消息总数将重置为0。

根据用户的需求,有以下几个功能,需要你来实现:
(1)recv:收到一条好友消息,对于手动置顶好友的消息,将在“手动置顶好友列表”里置顶;对于其他好友的消息,将在“手动置顶好友列表”之下的消息列表里置顶,同时都需要显示该好友的消息总数。
(2)view:查看好友消息,将使该好友消息数变为0。
(3)up:手动置顶好友。
(4)down:取消手动置顶。
(5)delete:删除好友消息,这个操作将使该好友从消息列表中删除,同时取消对该好友的手动置顶(如果存在的话)。

假设初始消息列表为空,经过了一系列好友消息的操作之后,最终的消息列表将是怎么样的呢?

输入描述:

第一行输入一个整数T(表示样例个数)
接下来T组样例。
每组样例
第一行输入一个整数M,表示操作数(1≤M≤1000000);
接下来M行,
每行输入一个操作,由一个操作类型和一个好友id构成,之间以空格分开,操作类型如上面5个英文单词表示,
例如:“recv 123456”表示接收到id为123456的好友的一条消息,“delete 123456”表示在消息列表中删除 id 为123456的好友的消息记录。
为了简化问题,一开始消息列表为空并假设好友名字id由六位数字“唯一”标识(000000≤id≤999999),
题目保证输入数据的一致性。

输出描述:

每组样例,
输出最后的消息列表,自顶向下,每行输出一个:“好友id 消息数”。
每组样例后空一行。
示例1

输入

1
13
recv 000001
recv 000002
up 000002
view 000001
recv 000002
recv 000004
up 000004
up 000001
recv 000004
recv 000003
view 000001
view 000004
down 000002

输出

000004 0
000001 0
000003 1
000002 2

模拟题,由于是最近接到的消息显示在上面,就可以用栈来模拟,vis表示是否是顶置,del表示是否删除,遇见recv就压入栈里,计数加1。

当然,这样的话栈里就有很多重复的id了。取时,只取最上面的而且没有删除的数字就行,被顶置的和没被顶置的分开来。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 const int N = 1000010;
 5 int ans[N], id, t, m;
 6 bool vis[N], del[N], vis1[N];
 7 string s;
 8 stack<int> st;
 9 queue<int> que1, que2;
10 int main() {
11     ios::sync_with_stdio(false);
12     cout.tie(0);
13     cin.tie(0);
14     cin >> t;
15     while(t--) {
16         cin >> m;
17         while(m--) {
18             cin >> s >> id;
19             if(s == "recv") {
20                 st.push(id);
21                 ans[id]++;
22                 del[id] = false;
23             }else if(s == "up") {
24                 vis[id] = true;
25             }else if(s == "view") {
26                 ans[id] = 0;
27             } else if(s == "down") {
28                 vis[id] = false;
29             } else if(s == "delete") {
30                 del[id] = true;
31                 ans[id] = 0;
32                 vis[id] = false;
33             }
34         }
35         while(st.size()) {
36             id = st.top();
37             st.pop();
38             if(vis1[id]) continue;
39             if(vis[id] && !del[id]) que1.push(id);
40             if(!vis[id] && !del[id]) que2.push(id);
41             vis1[id] = true;
42         }
43         while(que1.size()) {
44             id = que1.front();
45             que1.pop();
46             printf("%06d %d\n",id,ans[id]);
47         }
48         while(que2.size()) {
49             id = que2.front();
50             que2.pop();
51             printf("%06d %d\n",id,ans[id]);
52         }
53         memset(vis,0,sizeof(vis));
54         memset(vis1, 0, sizeof(vis1));
55         memset(del,0,sizeof(del));
56         memset(ans,0,sizeof(ans));
57         printf("\n");
58     }
59     return 0;
60 }

 

f 解方程

题目描述

对于方程 2018 * x ^ 4 + 21 * x + 5 * x ^ 3 + 5 * x ^ 2 + 14 = Y,
告诉你Y的值,你能找出方程在0~100之间的解吗?

输入描述:

第一行输入一个正整数T(表示样例个数)
接下来T组样例
每组样例一行,输入一个实数Y

输出描述:

一行输出一个样例对应的结果,
输出方程在0~100之间的解,保留小数点后4位小数;如果不存在,输出 -1
示例1

输入

2
1
20180421

输出

-1
9.9993

很明显是单调递增,值域是[14,201805052114],在这里面的一定有值,然后从0 - 100 每次加0.0001,取最接近y的f(x)值。
 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <cmath>
 4 #include <cstring>
 5 using namespace std;
 6 #define ll long long
 7 const int N = 11;
 8 double f(double x) {
 9     return 2018*x*x*x*x+21*x+5*x*x*x+5*x*x+14;
10 }
11 int main() {
12     int t;
13     // printf("%.8lf\n",f(100));
14     double MAX = 201805052114;
15     cin >> t;
16     while (t--) {
17         double y;
18         cin >> y;
19         if(y < 14 || y > 201805052114) {
20             printf("-1\n");
21             continue;
22         }
23         double MIN = 1000000;
24         double x;
25         for(double i = 0; i <= 100; i += 0.0001) {
26             if(fabs(f(i)-y) < MIN) {
27                 MIN = fabs(f(i)-y);
28                 x = i;
29             }
30         }
31         printf("%.4lf\n",x);
32     }
33     return 0;
34 }

G 小Q的口袋校园

题目描述

周末,小Q喜欢在PU口袋校园上参加各种活动刷绩点,体验丰富多彩的大学生活。
但是每个活动有各自的开始时间、结束时间、Happy值以及绩点数,活动之间可能存在时间冲突。
小Q是一个认真踏实的女孩,她在同一时间只会参加一个活动。
给出每一天的活动数,求小Q在同一天内所能获得的最大Happy值 与 绩点数。
小Q是一个活泼开朗的女孩,她总是寻求最大的Happy值,如果Happy值相同,才会尽可能使绩点数更多。

输入描述:

第一行输入一个整数T(表示样例个数)
接下来T组样例
每组样例第一行输入一个整数N(表示有几项活动)
接下来N行,每行输入s,e,h,p 4个整数,分别代表一个活动的开始时间、结束时间、Happy值以及绩点数
0<=s<e<=24,1<=h,p<=100,1<=T,N<=20

输出描述:

输出T行
一行输出一个样例对应的结果
小Q在一天内所能获得的最大 Happy值 与 绩点数
示例1

输入

1
4
1 3 1 1
2 5 2 1
3 7 2 1
5 8 1 2

输出

3 3

说明

有两种方案
1)选择 第1、3两个活动,可以获得 Happy值 3 和 绩点数 2;
2)选择 第2、4两个活动,可以获得 Happy值 3 和 绩点数 3.


看题解的,很巧妙的思路。
 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <cstring>
 4 #include <algorithm>
 5 using namespace std;
 6 #define ll long long
 7 const int N = 30;
 8 int h[N], p[N];
 9 struct Nod {
10     int s, e, h, p;
11 }nod[22];
12 bool cmp(Nod &a, Nod &b) {
13     return a.s < b.s;
14 }
15 int main() {
16     int t;
17     cin >> t;
18     while(t--) {
19         memset(h,0,sizeof(h));
20         memset(p,0,sizeof(p));
21         int n;
22         cin >> n;
23         for(int i = 0; i < n; i ++) {
24             cin >> nod[i].s >> nod[i].e >> nod[i].h >> nod[i].p;
25         }
26         sort(nod,nod+n,cmp);
27         for(int i = 0; i < n; i ++) {
28             for(int j = nod[i].e; j <= 24; j ++) {
29                 if(h[j] < h[nod[i].s] + nod[i].h) {
30                     h[j] = h[nod[i].s] + nod[i].h;
31                     p[j] = p[nod[i].s] + nod[i].p;
32                 } else if(h[j] == h[nod[i].s] + nod[i].h) {
33                     p[j] = p[nod[i].s] + nod[i].p;
34                 }
35             }
36         }
37         cout << h[24] << ' ' << p[24] << endl;
38     }
39     return 0;
40 }

H 小P的数学问题

题目描述

晚上,小P喜欢在寝室里一个个静静的学习或者思考,享受自由自在的单身生活。
他总是能从所学的知识散发出奇妙的思维。
今天他想到了一个简单的阶乘问题,
0!= 1
1!= 1
2!= 1 * 2 = 2
3!= 1 * 2 * 3 = 6
4!= 1 * 2 * 3 *4 = 24
5!= 1 * 2 * 3 *4 * 5 = 120
如果 n=1000000000,那么n的阶乘会是多少呢,小P当然知道啦,那么你知道吗?

输入描述:

第一行输入一个整数T(表示样例个数)
接下来T组样例
每组样例一行,输入一个整数N(0<=N<=1000000000)

输出描述:

输出T行
每一行输出N的阶乘 N!(由于这个数比较大,所以只要输出其对1000000007取膜的结果即可)
示例1

输入

2
0
1000000000

输出

1
698611116

分块打表,每隔1e7算一个值,这样计算复杂度是1e7 1秒可以算出来。
 1 #include <iostream>
 2 #include <stdio.h>
 3 #define ll long long
 4 using namespace std;
 5 const ll mod = 1000000007;
 6 ll a[110]={1,682498929,491101308,76479948,723816384,67347853,27368307,
 7 625544428,199888908,888050723,927880474,281863274,661224977,623534362,
 8 970055531,261384175,195888993,66404266,547665832,109838563,933245637,
 9 724691727,368925948,268838846,136026497,112390913,135498044,217544623,
10 419363534,500780548,668123525,128487469,30977140,522049725,309058615,
11 386027524,189239124,148528617,940567523,917084264,429277690,996164327,
12 358655417,568392357,780072518,462639908,275105629,909210595,99199382,
13 703397904,733333339,97830135,608823837,256141983,141827977,696628828,
14 637939935,811575797,848924691,131772368,724464507,272814771,326159309,
15 456152084,903466878,92255682,769795511,373745190,606241871,825871994,
16 957939114,435887178,852304035,663307737,375297772,217598709,624148346,
17 671734977,624500515,748510389,203191898,423951674,629786193,672850561,
18 814362881,823845496,116667533,256473217,627655552,245795606,586445753,
19 172114298,193781724,778983779,83868974,315103615,965785236,492741665,
20 377329025,847549272,698611116};
21 int main(){
22     ios::sync_with_stdio(false);
23     cin.tie(0);
24     cout.tie(0);
25     ll n,t;
26     cin >> t;
27     while(t--) {
28         cin >> n;
29         int cnt = n / 1e7;
30         ll ans = a[cnt];
31         for(ll i = 1e7*cnt+1; i <= n; i ++) {
32             ans = ans*i%mod;
33         }
34         cout << ans << endl;
35     }
36     return 0;
37 }

I 小P和小Q

题目描述

小P和小Q是好朋友,今天他们一起玩一个有趣的游戏。
他们的初始积分都为1,赢的人可以将自己的分数乘以 (K的平方),而输的人也能乘以K。
他们玩的太开心了,以至于忘了自己玩了多久,甚至 K 是多少和游戏进行的回合数 N 都忘了。
现在给出他们俩最终的积分a,b,请问是否存在正整数K、N满足这样的积分,判断他们的游戏结果是否可信。

输入描述:

第一行输入一个整数T(表示样例个数)
接下来T组样例
每组样例一行,输入两个正整数a,b(0<a,b<=1e9)

输出描述:

输出T行
一行输出一个样例对应的结果
若结果可信,输出 Yes
否则,输出 No
示例1

输入

6
2 4
75 45
8 8
16 16
247 994
1000000000 1000000

输出

Yes
Yes
Yes
No
No
Yes

备注:

每回合的K可能不同



这题好坑,我写的是ll d = cbrt(c);一直错误,赛后看别人的才知道一定要写float,写double还不行。写成ll d = (float)cbrt(c);
 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <cstring>
 4 #include <cmath>
 5 using namespace std;
 6 #define ll long long
 7 const int N = 11;
 8 int main() {
 9     int t;
10     cin >> t;
11     while(t--) {
12         ll a, b;
13         cin >> a >> b;
14         ll c = a*b;
15         ll d = (float)cbrt(c);
16         if(d*d*d != c) printf("No\n");
17         else printf("Yes\n");
18     }
19     return 0;
20 }

 

posted @ 2018-04-21 19:34  starry_sky  阅读(315)  评论(0编辑  收藏  举报