noip模拟测试34
noip模拟测试34
前言:因为这次考试题目太好看了,所以把题目粘了过来
t1 666
题目:
不忘初心
小 π 假期在家无聊,打开了某弹幕直播网站。
突然,有一个精彩的镜头。
小 π 看到了满屏的 6,其中,有 666、也有 666666、也有 6666666666 . . .
小 π 也想发个弹幕,他打算发 n 个 6。
然而当他按下第一个 6 时,键盘上 6 的键坏了。
这时,弹幕框里只有 1 个 6。
键盘坏了什么的不要紧,先把弹幕发了才是正事。
于是小 π 打算用复制粘贴这类操作来生成这 n 个 6。
具体的说,小 π 电脑的操作系统有唯一的一块剪贴板,初始为空,现在小π 一共有三种操作:
第 1 种操作,全选然后复制。这样会把剪贴板里的内容设置为当前弹幕框内内容。
第 2 种操作,粘贴。会把剪贴板中的内容连接到弹幕框现有的内容后面。
第 3 种操作,backspace。会把在当前弹幕框中删除一个 6。
小 π 很好奇现在生成想要的 n 个 6 至少需要多少次操作,来找到了学信息学竞赛的你。
注意本题时间限制
数据范围
\(0 \leq n \leq 1000000\)
思路
考虑dp转移,\(dp_i\)就表示转移到i的最小次数是多少,用bfs的思路去写就好了
代码:
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 1e6 + 500;
inline int read () {
int x = 0, f = 1; char ch = getchar();
for (;!isdigit(ch); ch = getchar()) if (ch == '-') f = -1;
for (; isdigit(ch); ch = getchar()) x = x * 10 + ch - '0';
return x * f;
}
int n, dp[maxn], bs;
int main () {
freopen ("six.in", "r", stdin);
freopen ("six.out", "w", stdout);
n = read();
memset (dp, -1, sizeof dp);
dp[1] = 0;
register int cur;
while (dp[n] == -1) {
++bs;
for (register int i = 1; i <= n + 50; ++i) {
if (dp[i] == -1) continue;
cur = i * (bs - dp[i]);
if (cur <= n + 50 && dp[cur] == -1) dp[cur] = bs;
if (dp[i - 1] == -1) dp[i - 1] = dp[i] + 1;
}
}
printf ("%d\n", dp[n]);
return 0;
}
t2 春思
题目:
蝶恋花·春景
花褪残红青杏小。燕子飞时,绿水人家绕。枝上柳绵吹又少。天涯何处无芳草!
墙里秋千墙外道。墙外行人,墙里佳人笑。笑渐不闻声渐悄。多情却被无情恼。
(本词是伤春之作,写春景清新秀丽。同时,景中又有情理,我们仍用何处无芳草(知音)以自慰自勉。苏轼的多情却被无情恼,也不仅仅局限于对佳人的相思。)
春意涟涟,烟柳画桥,风帘翠幕,参差十万人家。苏子漫步于江堤之上,见妖童媛女,荡舟心许。闻墙内墙外,笑意恬恬。叹春光甚好,心有所思。
他思考了这么一个问题:有一个很大的数字,被表示为\(A^B\),他想求出其所有约数(即因子)之和,最后答案再模上9901,作为一代文豪,他表示不会算,请你帮帮他。
数据范围
\(A\) \(\leq\) \(10^{12}\), \(B\) \(\leq\) \(10^{12}\)
思路
运用约数和定理,\(n = p_1 ^{a_1} p_2 ^{a_2}p_3 ^{a_3}...p_k ^{a_k}\), \(sum = \displaystyle \prod_{i =1}^n \sum_{j = 0}^{a_i}p_i^j\)
处理B就把\(a_i\)乘上B就好了
代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#define ll long long
using namespace std;
const int maxn = 1e6 + 50, INF = 0x3f3f3f3f, mod = 9901;
inline long long read () {
long long x = 0, f = 1; char ch = getchar();
for (;!isdigit(ch); ch = getchar()) if (ch == '-') f = -1;
for (; isdigit(ch); ch = getchar()) x = x * 10 + ch - '0';
return x * f;
}
long long a, b, sqr, cnt, ans = 1ll;
long long prime[maxn], num[maxn];
inline long long qpow (register long long a, register long long b) {
register long long ans = 1ll;
while (b) {
if (b & 1) ans = ans * a % mod;
a = a * a % mod, b >>= 1;
}
return ans;
}
int main () {
freopen ("spring.in", "r", stdin);
freopen ("spring.out", "w", stdout);
a = read(), b = read(), sqr = sqrt (a);
for (register long long i = 2; i <= sqr; i ++) {
if (a % i == 0) {
prime[++ cnt] = i % mod;
while (a % i == 0) {
num[cnt] ++, a /= i;
}
}
}
if (a != 1) prime[++ cnt] = a % mod, num[cnt] ++;
for (register int i = 1; i <= cnt; i ++) {
if (prime[i] == 1) {
ans = ans * (num[i] * b % mod + 1) % mod;
}
else {
ans = ans * (qpow (prime[i], num[i] * b + 1) - 1ll) % mod * qpow (prime[i] - 1, mod - 2) % mod;
}
}
printf ("%lld\n", ans);
return 0;
}
t3 密州盛宴
题目
江城子·密州出猎
老夫聊发少年狂,左牵黄,右擎苍,锦帽貂裘,千骑卷平冈。为报倾城随太守,亲射虎,看孙郎。
酒酣胸胆尚开张,鬓微霜,又何妨!持节云中,何日遣冯唐?会挽雕弓如满月,西北望,射天狼。
(这首词通过描写一次出猎的壮观场面,借历史典故抒发了作者杀敌为国的雄心壮志,体现了为了效力抗击侵略的豪情壮志,并委婉地表达了期盼得到朝廷重用的愿望)
东坡出猎密州,虽年老体衰,但有杀敌为国的雄心壮志,获得了乡亲们的盛情款待。具体说他们请东坡吃\(2n\)盘菜,这些菜排成了长长的一列。因为东坡是著名的美食家,所以东坡只会吃其中的某些菜品,而乡亲们是不挑食的。并且东坡或者乡亲们吃掉一份菜的时间都是1分钟。
(注:你可以把乡亲们看作一个人)
我们用一行01序列表示菜品品种, 表示东坡不吃的菜, 表示东坡吃的菜。他们会尽量按顺序吃菜,具体来说规则是:
1.如果现在菜品开头是0 ,现在东坡和乡亲们都没有在吃菜,显然是乡亲们吃那一份菜。
2.如果现在菜品开头是0 ,现在东坡在吃菜,显然是乡亲们吃那一份菜。
3.如果现在菜品开头是0 ,现在乡亲们在吃菜,东坡就会找到后面第一份为1的菜吃。(如果没有了就不吃了)
4.如果现在菜品开头是1 ,现在东坡和乡亲们都没有在吃菜,那么优先东坡吃那一份菜。
5.如果现在菜品开头是1 ,现在东坡在吃菜,那么乡亲们吃那一份菜。
6.如果现在菜品开头是1 ,现在乡亲们在吃菜,显然是东坡吃那一份菜。
我们不考虑拿菜所需的时间,只计算吃菜的时间。因为菜放久了会冷掉,所以东坡和乡亲们需要在\(n\)钟内吃完所有的菜。显然有一些顺序是不对的,所以乡亲们会在开饭前重新排列菜的顺序。
我们记某份菜往后移动\(C\)位的困难值为\(C\), (而菜品前移是不困难的),对于一种合法的方案,最后的\(C\)值为所有菜\(C\)的最大值。
现在请你算一算,对于所有合法的方案,\(C\)的最小值是多少?如果不存在合法方案,请你输出"-1"(不含引号)
数据范围
思路
由于讲题时没有组织好语言去讲,中午睡觉的时候想了想赶紧写篇题解向乡亲们(雾)谢罪(动动的代码在判断-1的地方错了,请认准唯一正解)
很显然的是前面的0越多越好,这样其他人可以不吃1,尽量多的吃0,另外也可以保证东坡每时每刻都有1吃
可以考虑一种特殊情况,就是其他人都尽量把0都吃完再吃一,此时一定有解,但是显然多了很多不必要的交换操作,也就是说其他人也可以吃1,不一定吃0
举个例子:
1 1 1 1 1 1 1 0 0 0
这种情况下我们先让其他人吃 0, 可以得到该序列
1 0 1 0 1 0 1 1 1 1
最多的交换了6次
但是由于其他人也可以吃1,并且可以吃两个1,所以我们不妨把这个序列做出该变化
1 1 1 1 1 0 1 0 1 0
这样我们只交换了两次就可以完成
也就是其中我们有四次的交换是多余的,因为在前面我们可以先吃两个1,而两种方案差的交换次数也是很显然,即全序列中1的个数减去0的个数
代码:
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
#define int long long
inline int read () {
int x = 0, f = 1; char ch = getchar();
for (;!isdigit(ch); ch = getchar()) if (ch == '-') f = -1;
for (; isdigit(ch); ch = getchar()) x = x * 10 + ch - '0';
return x * f;
}
const int maxn = 1e6 + 50;
int n, m;
char S[maxn], now[maxn];
long long t;
long long ans = 0;
signed main () {
freopen ("meal.in", "r", stdin);
freopen ("meal.out", "w", stdout);
while (1) {
n = read(), m = read();
if (n == 0 && m == 0) return 0;
long long cnt0 = 0, cnt1 = 0;
ans = 0;
register int len;
register int js0 = 0, js1 = 0;
register int maxx = -0x3f3f3f3f;
for (register int i = 1; i <= m; i++) {
scanf ("%s", now + 1);
t = read();
len = strlen (now + 1);
js0 = js1 = 0;
maxx = -0x7fffffff;
maxx = max (js0 - js1, maxx);
for (register int j = 1; j <= len; j++) {
if (now[j] == '0') {
maxx = max (js1 - js0, maxx);
++js0;
} else {
++js1;
}
}
if (js0 == 0) {
cnt0 += js0 * t, cnt1 += js1 * t;
continue;
}
ans = max (ans, cnt1 - cnt0 + maxx);
ans = max (ans, cnt1 - cnt0 + (js1 - js0) * (t - 1) + maxx);
cnt0 += js0 * t, cnt1 += js1 * t;
}
if (cnt0 > cnt1) {
puts("-1");
} else if (cnt0 == cnt1) {
cout<<max((ans - 1), 0ll)<<endl;
} else {
cout<<max(0ll, (ans - 1 - (cnt1 - cnt0)))<<endl;
}
}
return 0;
}
t4 赤壁情
题目
前赤壁赋
壬戌之秋,七月既望,苏子与客泛舟游于赤壁之下。清风徐来,水波不兴。举酒属客,诵明月之诗,歌窈窕之章。少焉,月出于东山之上,徘徊于斗牛之间。白露横江,水光接天。纵一苇之所如,凌万顷之茫然。浩浩乎如冯虚御风,而不知其所止;飘飘乎如遗世独立,羽化而登仙。于是饮酒乐甚,扣舷而歌之。歌曰:“桂棹兮兰桨,击空明兮溯流光。渺渺兮予怀,望美人兮天一方。”客有吹洞箫者,倚歌而和之。其声呜呜然,如怨如慕,如泣如诉;余音袅袅,不绝如缕。舞幽壑之潜蛟,泣孤舟之嫠妇。
苏子愀然,正襟危坐,而问客曰:“何为其然也?”客曰:“‘月明星稀,乌鹊南飞。’此非曹孟德之诗乎?西望夏口,东望武昌,山川相缪,郁乎苍苍,此非孟德之困于周郎者乎?方其破荆州,下江陵,顺流而东也,舳舻千里,旌旗蔽空,酾酒临江,横槊赋诗,固一世之雄也,而今安在哉?况吾与子渔樵于江渚之上,侣鱼虾而友麋鹿,驾一叶之扁舟,举匏樽以相属。寄蜉蝣于天地,渺沧海之一粟。哀吾生之须臾,羡长江之无穷。挟飞仙以遨游,抱明月而长终。知不可乎骤得,托遗响于悲风。” 苏子曰:“客亦知夫水与月乎?逝者如斯,而未尝往也;盈虚者如彼,而卒莫消长也。盖将自其变者而观之,则天地曾不能以一瞬;自其不变者而观之,则物与我皆无尽也,而又何羡乎!且夫天地之间,物各有主,苟非吾之所有,虽一毫而莫取。惟江上之清风,与山间之明月,耳得之而为声,目遇之而成色,取之无禁,用之不竭。是造物者之无尽藏也,而吾与子之所共适。”
客喜而笑,洗盏更酌。肴核既尽,杯盘狼籍。相与枕藉乎舟中,不知东方之既白。
赤壁水茫茫,惊苏子,动其情,而作千古名篇赤壁赋。他立于舟头,寄蜉蝣于天地,渺沧海之一粟。
这世上,生老病死,男女情爱,事业大绩,似乎都不放于眼下。这里,但有我与天地,与赤壁灵水。脱红尘于此,但为我愿。
叹浪之忽急忽缓,忽汹忽静,而谁又明赤壁真谛?苏子放眼望去,一排江波涌来,他想明赤壁之意,于是他将一排江波抽象成一个1到\(N\)的排列\(P[1..N]\),定义赤壁之意如下:
\(L = |P_2 - P_1| + |P_3-P_2| + ... + |P_n-P_{n-1}|\)
给出\(N\)和\(M\),苏子想知道:随机一个\(N,M\)和\(K\),\(N\),\(M\)如上,\(K\)为小数点后保留位数
然后我不会,咕咕咕,扔个60分代码溜了(我就是喜欢题面而已)
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
inline int read () {
int x = 0, f = 1; char ch = getchar();
for (;!isdigit(ch); ch = getchar()) if (ch == '-') f = -1;
for (; isdigit(ch); ch = getchar()) x = x * 10 + ch - '0';
return x * f;
}
int n, m, k;
int path[105];
int tong[105];
int cnt;
void dfs (int now) {
if (now == n + 1) {
register int ans = 0;
for (register int i = 1; i < n; i++) {
ans += abs(path[i] - path[i + 1]);
}
if (ans >= m) ++cnt;
}
for (register int i = 1; i <= n; i++) {
if (tong[i]) continue;
tong[i] = true;
path[now] = i;
dfs (now + 1);
tong[i] = false;
}
}
int a[105];
double ans;
int main () {
freopen ("river.in", "r", stdin);
freopen ("river.out", "w", stdout);
n = read(), m = read(), k = read();
if (n <= 10) {
dfs (1);
register long long fm = 1;
for (register int i = 1; i <= n; i++) {
fm *= i;
}
ans = (double)cnt / (double)fm;
if (k == 0) printf ("%.0lf", ans);
else if (k == 1) printf ("%.1lf", ans);
else if (k == 2) printf ("%.2lf", ans);
else if (k == 3) printf ("%.3lf", ans);
else if (k == 4) printf ("%.4lf", ans);
else if (k == 5) printf ("%.5lf", ans);
else if (k == 6) printf ("%.6lf", ans);
else if (k == 7) printf ("%.7lf", ans);
else if (k == 8) printf ("%.8lf", ans);
} else {
register int i, j, t;
for (i = 1; i <= n; ++i) {
a[i] = i;
}
register int s = 0;
register int Times = 80000000 / n;
for (i = 0; i < Times; ++i) {
random_shuffle (a, a + n);
t = 0;
for (j = 0; j < n - 1; ++j) t += a[j+1] - a[j] > 0 ? a[j + 1] - a[j] : a[j] - a[j + 1];
t >= m ? ++s : 1;
}
if (k == 0) printf ("%.0lf", s / (double)Times);
else if (k == 1) printf ("%.1lf", s / (double)Times);
else if (k == 2) printf ("%.2lf", s / (double)Times);
else if (k == 3) printf ("%.3lf", s / (double)Times);
else if (k == 4) printf ("%.4lf", s / (double)Times);
else if (k == 5) printf ("%.5lf", s / (double)Times);
else if (k == 6) printf ("%.6lf", s / (double)Times);
else if (k == 7) printf ("%.7lf", s / (double)Times);
else if (k == 8) printf ("%.8lf", s / (double)Times);
}
return 0;
}