NOIP2014-3-15模拟赛

Problem 1 高级打字机(type.cpp/c/pas)

【题目描述】

早苗入手了最新的高级打字机。最新款自然有着与以往不同的功能,那就是它具备撤销功能,厉害吧。

请为这种高级打字机设计一个程序,支持如下3种操作:

1.T x:在文章末尾打下一个小写字母x。(type操作)

2.U x:撤销最后的x次修改操作。(Undo操作)

(注意Query操作并不算修改操作)

3.Q x:询问当前文章中第x个字母并输出。(Query操作)

文章一开始可以视为空串。

【输入格式】

第1行:一个整数n,表示操作数量。

以下n行,每行一个命令。保证输入的命令合法。

【输出格式】

每行输出一个字母,表示Query操作的答案。

【样例输入】

7

T a

T b

T c

Q 2

U 2

T c

Q 2

【样例输出】

b

c

【数据范围】

对于40%的数据 n<=200;

对于100%的数据 n<=100000;保证Undo操作不会撤销Undo操作。

<高级挑战>

对于200%的数据 n<=100000;Undo操作可以撤销Undo操作。

<IOI挑战>

必须使用在线算法完成该题。

Problem 2 不等数列(num.cpp/c/pas)

【题目描述】

将1到n任意排列,然后在排列的每两个数之间根据他们的大小关系插入“>”和“<”。问在所有排列中,有多少个排列恰好有k个“<”。答案对2012取模。

【输入格式】

第一行2个整数n,k。

【输出格式】

一个整数表示答案。

【样例输入】

5 2

【样例输出】

66

【数据范围】

对于30%的数据:n <= 10

对于100%的数据:k < n <= 1000,

Problem 3 经营与开发(exploit.cpp/c/pas)

【题目描述】

4X概念体系,是指在PC战略游戏中一种相当普及和成熟的系统概念,得名自4个同样以“EX”为开头的英语单词。

eXplore(探索)

eXpand(拓张与发展)

eXploit(经营与开发)

eXterminate(征服)

——维基百科

今次我们着重考虑exploit部分,并将其模型简化:

你驾驶着一台带有钻头(初始能力值w)的飞船,按既定路线依次飞过n个星球。

星球笼统的分为2类:资源型和维修型。(p为钻头当前能力值)

1.资源型:含矿物质量a[i],若选择开采,则得到a[i]*p的金钱,之后钻头损耗k%,即p=p*(1-0.01k)

2.维修型:维护费用b[i],若选择维修,则支付b[i]*p的金钱,之后钻头修复c%,即p=p*(1+0.01c)

注:维修后钻头的能力值可以超过初始值(你可以认为是翻修+升级)

请作为舰长的你仔细抉择以最大化收入。

【输入格式】

第一行4个整数n,k,c,w。

以下n行,每行2个整数type,x。

type为1则代表其为资源型星球,x为其矿物质含量a[i];

type为2则代表其为维修型星球,x为其维护费用b[i];

【输出格式】

一个实数(保留2位小数),表示最大的收入。

【样例输入】

5 50 50 10

1 10

1 20

2 10

2 20

1 30

【样例输出】

375.00

【数据范围】

对于30%的数据 n<=100

另有20%的数据 n<=1000;k=100

对于100%的数据 n<=100000; 0<=k,c,w,a[i],b[i]<=100;保证答案不超过10^9



T1:

这题看起来挺简单,实际上比较麻烦

对于50%的数据,代码很好写:

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<algorithm>
 4 #include<cstring>
 5 #define MAXN 100005
 6 using namespace std;
 7 char s[MAXN];
 8 int p;
 9 int main()
10 {
11     int T;
12     scanf("%d",&T);
13     for(int i=1;i<=T;i++){
14         char c;
15         scanf(" %c",&c);
16         if(‘T‘==c){
17             char x;
18             scanf(" %c",&x);
19             s[++p]=x;
20         }
21         else{
22             int x;
23             scanf("%d",&x);
24             if(‘U‘==c){
25                 p-=x;
26             }
27             else{
28                 printf("%c\n",s[x]);
29             }
30         }
31     }
32     return 0;
33 }

Code1

对于50%+的数据,就有点麻烦了,我是直接暴力转移的,80分,两个点MLE

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<vector>
 6 #define MAXN 100005
 7 using namespace std;
 8 int n;
 9 char p[MAXN],X[MAXN];
10 int b[MAXN],to[MAXN];
11 vector<char> s[MAXN];
12 vector<char> find(int x){
13     if(b[x]||!x){
14         return s[x];
15     }
16     s[x]=find(to[x]);
17     if(‘T‘==p[x])
18         s[x].push_back(X[x]);
19     b[x]=1;
20     return s[x];
21 }
22 int main()
23 {
24 //    freopen("type06.in","r",stdin);
25 //    freopen("my.out","w",stdout);
26     scanf("%d",&n);
27     scanf(" %c",&p[1]);
28     scanf(" %c",&p[1]);
29     s[1].push_back(p[1]);
30     b[1]=1;
31     for(int i=2;i<=n;i++){
32         scanf(" %c",&p[i]);
33         if(‘T‘==p[i]){
34             scanf(" %c",&X[i]);
35             to[i]=i-1;
36         }
37         else{
38             int x;
39             scanf("%d",&x);
40             if(‘U‘==p[i]){
41                 to[i]=i-x-1;
42             }
43             else{
44                 vector<char> temp(find(i-1));
45                 printf("%c\n",temp[x-1]);
46                 i--;
47                 n--;
48             }
49         }
50 //        for(int j=0;j<s[i].size();j++){
51 //            printf("%c",s[i][j]);
52 //        }
53 //        printf("\n");
54     }
55     return 0;
56 }

Code2

正解是巧妙利用转移顺序的离线算法,把转移看成一棵树,走欧拉路使得复杂度降为O(n)

(PS:代码是标程代码,我的不知道怎么回事不能AC,调了一下午ToT)

 1 #include<cstdio>
 2 #include<vector>
 3 #define pb push_back
 4 #define rep(i,n) for(int i=0;i<n;i++)
 5
 6 using namespace std;
 7
 8 const int maxn=100010;
 9 int n,q,x,v,sz,tot,fa[maxn],en[maxn],pre[maxn],g[maxn],ans[maxn];
10 char ch,a[maxn],sk[maxn];
11
12 vector <int> lk[maxn];
13
14 void Ins(int u,int v)
15 {
16     pre[++sz]=en[u];en[u]=sz;g[sz]=v;
17 }
18 void Type()
19 {
20     scanf("%s",&ch);
21     a[tot]=ch;
22     tot++;
23     fa[tot]=tot-1;
24
25 }
26 void Undo()
27 {
28     scanf("%d",&x);
29     tot++;
30     Ins(tot-x-1,tot);
31     fa[tot]=tot-x-1;
32 }
33 void Query()
34 {
35     scanf("%d",&x);
36     lk[tot].pb(q);
37     ans[q++]=x;
38 }
39
40 void DFS()
41 {
42     tot=x=0;
43     for(x=0;;)
44     {
45         if (en[x])
46         {
47             v=g[en[x]];
48             en[x]=pre[en[x]];
49             x=v;continue;
50         }
51         if (a[x])
52         {
53             sk[++tot]=a[x];
54             a[x]=0;
55             x++;continue;
56         }
57         rep(i,lk[x].size())
58         {
59             v=lk[x][i];
60             ans[v]=sk[ans[v]];
61         }
62         if (fa[x]+1==x) tot--;
63         if (!x) return;
64         x=fa[x];
65     }
66 }
67 int main()
68 {
69 //    freopen("type.in","r",stdin);
70 //    freopen("type.out","w",stdout);
71     scanf("%d\n",&n);
72     rep(i,n)
73     {
74         scanf("%s",&ch);
75         switch (ch)
76         {
77             case ‘T‘:Type();break;
78             case ‘U‘:Undo();break;
79             case ‘Q‘:Query();break;
80         }
81     }
82     DFS();
83     rep(i,q) printf("%c\n",ans[i]);
84     return 0;
85 }

Code3



T2:

这个想想看下数据范围1000,1000,肯定是dp了

考虑把n插入n-1个数中去,分类讨论下,即可得到状态转移方程:

f[i][j]=f[i-1][j-1]*(i-j)+f[i-1][j]*(j+1)

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<algorithm>
 4 #include<cstring>
 5 #define MAXN 1005
 6 #define MOD 2012
 7 using namespace std;
 8 int f[MAXN][MAXN];
 9 int n,k;
10 int main()
11 {
12     scanf("%d%d",&n,&k);
13     for(int i=1;i<=n;i++){
14         f[i][0]=1;
15     }
16     for(int i=2;i<=n;i++){
17         for(int j=1;j<n;j++){
18             f[i][j]=(f[i-1][j-1]*(i-j)+f[i-1][j]*(j+1))%MOD;
19         }
20     }
21     printf("%d\n",f[n][k]);
22     return 0;
23 }

Code4



T3:

这题我想了好久啊,还是没有什么思路,泪奔~~~~~o(>_<)o ~~

暴力算法:

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<vector>
 6 #define MAXN 100005
 7 using namespace std;
 8 int n;
 9 double k,c,w;
10 vector<pair<double,double> > s;
11 int main()
12 {
13 //    freopen("data.in","r",stdin);
14     scanf("%d",&n);
15     scanf("%lf%lf%lf",&k,&c,&w);
16     k=(1-0.01*k),c=(1+0.01*c);
17     s.push_back(make_pair(0,w));
18     double ans=0;
19     for(int i=1;i<=n;i++){
20         int type,t;
21         scanf("%d",&type);
22         int sz=s.size();
23         if(1==type){
24             scanf("%d",&t);
25             for(int j=0;j<sz;j++){
26                 double m=s[j].first,p=s[j].second;
27                 m+=t*p; p*=k;
28                 ans=max(ans,m);
29                 s.push_back(make_pair(m,p));
30             }
31         }
32         else{
33             scanf("%d",&t);
34             for(int j=0;j<sz;j++){
35                 double m=s[j].first,p=s[j].second;
36                 m-=t*p; p*=c;
37                 ans=max(ans,m);
38                 s.push_back(make_pair(m,p));
39             }
40         }
41     }
42     printf("%.2f",ans);
43     return 0;
44 }

Code5

得了10分QAQ

其实似乎可以优化下的,比如钱少性能又坏,那么肯定不要了

正解的思路妙啊~

发现开采:得到a[i]*p的金钱 之后钻头损耗k%,即p=p*(1-0.01k)

维修:支付b[i]*p的金钱,之后钻头修复c%,即p=p*(1+0.01c)

如果把最优解用一个多项式表示出来的话,肯定有一个公因数p!

那么我们就提取这个公因数,发现之后的无论咋搞,与p没关系了!

那么我们不妨认为p=1,然后万事大吉~

设f[i]表示开采i~n的最优解,且初始强度为1

那么有f[i]=max(f[i+1],f[i+1]*(1-0.01k)+a[i]或者是f[i+1]*(1+0.01c)-b[i])

ans为f[1]*w AC!

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<algorithm>
 4 #include<cstring>
 5 #define MAXN 100005
 6 using namespace std;
 7 int n;
 8 double f[MAXN];
 9 double k,c,w;
10 double a[MAXN],b[MAXN];
11
12 int main()
13 {
14     scanf("%d",&n);
15     scanf("%lf%lf%lf",&k,&c,&w);
16     k=(1-0.01*k),c=(1+0.01*c);
17     for(int i=1;i<=n;i++){
18         int t;
19         scanf("%d",&t);
20         scanf("%lf",&a[i]);
21         if(t==1){
22             b[i]=k;
23         }
24         else{
25             a[i]*=-1;
26             b[i]=c;
27         }
28     }
29     for(int i=n;i>=1;i--){
30         f[i]=max(f[i+1],f[i+1]*b[i]+a[i]);
31     }
32     printf("%.2f",f[1]*w);
33     return 0;
34 }

Code6

时间: 2024-08-30 17:05:34

NOIP2014-3-15模拟赛的相关文章

8.15模拟赛

T1.第K小数[问题描述]有两个正整数数列,元素个数分别为N和M.从两个数列中分别任取一个数相乘,这样一共可以得到N*M个数,询问这N*M个数中第K小数是多少.[输入格式]输入文件名为number.in.输入文件包含三行.第一行为三个正整数N,M和K.第二行为N个正整数,表示第一个数列.第三行为M个正整数,表述第二个数列.[输出格式]输出文件名为number.out.输出文件包含一行,一个正整数表示第K小数.[输入输出样例1 1 ]number.in 2 3 41 22 1 3 number.o

3.15 模拟赛

T1 T2 小R的箱子 T3 绯红之王 题目大意: 已知数列$a$,求$\sum\limits_{i=1}^n {a_i}^k$ 思路: 很久以前讲过的题,调了一年才搞出来 首先设$f_k=\sum\limits_{i=1}^n {a_i}^k$ , $g_k$表示对于所有$C_n^k$种选择的方法,$g_k=$所有方法内各个数相乘的和 例如数列中有四个数$a,b,c,d$ 则 $g_0=1$ $g_1=a+b+c+d$ $g_2=ab+ac+ad+bc+bd+cd$ $g_3=abc+abd+

9.15模拟赛

T1 np问题 题目描述 LYK喜欢研究一些比较困难的问题,比如np问题. 这次它又遇到一个棘手的np问题.问题是这个样子的:有两个数n和p,求n的阶乘对p取模后的结果. LYK觉得所有np问题都是没有多项式复杂度的算法的,所以它打算求助即将要参加noip的你,帮帮LYK吧! 输入输出格式 输入格式: 输入一行两个整数n,p. 输出格式: 输出一行一个整数表示答案. 输入输出样例 输入样例#1: 3 4 输出样例#1: 2 说明 对于20%的数据:n,p<=5. 对于40%的数据:n,p<=1

2017/9/15模拟赛

游戏(game) [问题描述] 小R和小H在玩某个双人联机小游戏,一开始两人所操控的角色各有1点力量值,而在游戏中,每通过一关都会掉落一些力量强化道具.奇怪的是,明明是双人小游戏,每关却都会掉落3个相同的力量强化道具,于是两人决定每关每人先拿一个,剩下一个猜拳决定给谁.一个力量强化道具能使一个角色的力量值变为原来的若干整数倍,同一关卡掉落的道具倍率都相同,而不同的关卡可能不同.小R从攻略上找到了一些会产生特殊效果的力量值组合,他想知道哪些组合是按他们的道具分配方式有可能在通过某关时达成的. [输

10月15日模拟赛题解

10月15日模拟赛题解 A 树 Description 给定一棵 \(n\) 个节点的树,每个节点有两个参数 \(a,~b\),对于每个节点,求子树中参数为 \(b\) 的所有节点的 \(a\) 之和 Limitations \(100\%\) \(1 \leq b \leq n \leq 10^5,~a \leq 1000\) \(60\%\) \(1 \leq b,n\leq 1000\) \(30\%\) \(1 \leq b, n \leq 10\) Solution 对于 \(30\%

8月15日模拟赛小结

今天的模拟赛是三道陈老师的题. 在 10:48 左右已经都能拿到了. 然后我觉得 T3 的蒙特卡洛算法不太稳, 于是调大参数. 本地不开 O2 需要 5s 左右, 开 O2 测需要 2s , 而时限是 3s . 我想着 XSY 也开了 O2 , 所以稳了. 结果比赛结束 T3 全部 TLE ..... 中途还犯了一次A题代码交到B题的错误. ZJT大爷说我从第 2 调到了倒数第 1 , QAQ . 得出结论: ① 很多评测机可能很辣鸡. 所以如果对于随机化算法之类的, 能开大迭代次数的标准是:

【BZOJ】【2741】【FOTILE模拟赛】L

可持久化Trie+分块 神题……Orz zyf & lyd 首先我们先将整个序列搞个前缀异或和,那么某一段的异或和,就变成了两个数的异或和,所以我们就将询问[某个区间中最大的区间异或和]改变成[某个区间中 max(两个数的异或和)] 要是我们能将所有[l,r]的答案都预处理出来,那么我们就可以O(1)回答了:然而我们并不能. 一个常见的折中方案:分块! 这里先假设我们实现了一个神奇的函数ask(l,r,x),可以帮我们求出[l,r]这个区间中的数,与x最大的异或值. 我们不预处理所有的左端点,我

10.30 NFLS-NOIP模拟赛 解题报告

总结:今天去了NOIP模拟赛,其实是几道USACO的经典的题目,第一题和最后一题都有思路,第二题是我一开始写了个spfa,写了一半中途发现应该是矩阵乘法,然后没做完,然后就没有然后了!第二题的暴力都没码QAQ 现在我来写解题报告了,有点饿了QAQ.. 第一题 题目 1: 架设电话线 [Jeffrey Wang, 2007] 最近,Farmer John的奶牛们越来越不满于牛棚里一塌糊涂的电话服务,于 是,她们要求FJ把那些老旧的电话线换成性能更好的新电话线.新的电话线架设 在已有的N(2 <=

bzoj 2741: 【FOTILE模拟赛】L 分塊+可持久化trie

2741: [FOTILE模拟赛]L Time Limit: 15 Sec  Memory Limit: 162 MBSubmit: 1116  Solved: 292[Submit][Status] Description FOTILE得到了一个长为N的序列A,为了拯救地球,他希望知道某些区间内的最大的连续XOR和. 即对于一个询问,你需要求出max(Ai xor Ai+1 xor Ai+2 ... xor Aj),其中l<=i<=j<=r. 为了体现在线操作,对于一个询问(x,y):

【题解】PAT团体程序设计天梯赛 - 模拟赛

由于本人愚笨,最后一题实在无力AC,于是只有前14题的题解Orz 总的来说,这次模拟赛的题目不算难,前14题基本上一眼就有思路,但是某些题写起来确实不太容易,编码复杂度有点高~ L1-1 N个数求和 设计一个分数类,重载加法运算符,注意要约分,用欧几里得算法求个最大公约数即可. 1 #include <cstdio> 2 3 long long abs(long long x) 4 { 5 return x < 0 ? -x : x; 6 } 7 8 long long gcd(long