NOIP模拟 9.09
AK300分
果实计数
(count.pas/.c/.cpp)
时间限制:1s,空间限制32MB
题目描述:
淘淘家有棵奇怪的苹果树,这棵树共有n+1层,标号为0~n。这棵树第0层只有一个节点,为根节点。已知这棵树为b叉树,且保证是一颗满b叉树。如图为一颗满3叉树。
现在,该树第n层的每个节点上都结出了一个苹果,淘淘想知道共结了多少苹果。由于数量可能很大,答案要求输出mod k后的结果。
输入描述:
给出第1层的节点数b和层数n和k.
输出描述:
输出苹果数mod k后的结果。
样例输入:
2 10 9
样例输出:
7
数据范围:
30%的数据保证:b<=100,n<=10, k<=100.
100%的数据保证:b<2^31,n<2^31,k<=2^15.
【题解】
嗯?求n层完全b叉树的节点数?
嗯。。等比数列求和公式。。不对,模数是k,1-q不一定有逆元。。嗯。分治nlog^2n算法。。
嗯。。嗯?
求完全b叉树第n层节点数?
woccccccccc
这题太神辣!!
传说中的二进制拆分倍增算法啊!
(简称快速幂)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 6 inline void read(long long &x) 7 { 8 x = 0;char ch = getchar(), c = ch; 9 while(ch < '0' || ch > '9')c = ch, ch = getchar(); 10 while(ch <= '9' && ch >= '0')x = x * 10 + ch - '0', ch = getchar(); 11 if(c == '-')x = -x; 12 } 13 14 long long b,n,k; 15 16 long long pow(long long a, long long b) 17 { 18 register long long r = 1, base = a%k; 19 for(;b;b >>= 1) 20 { 21 if(b & 1)r *= base, r %= k; 22 base *= base, base %= k; 23 } 24 return r%k; 25 } 26 27 int main() 28 { 29 read(b), read(n), read(k); 30 printf("%lld", pow(b,n)%k); 31 return 0; 32 }
打地鼠游戏
(mouse.pas/.c/.cpp)
时间限制:1s 空间限制:128MB
题目描述:
伟大的2320学长特别喜欢打地鼠游戏,这个游戏开始后,会在地板上冒出一些地鼠来,你可以用榔头去敲击这些地鼠,每个地鼠被敲击后,将会增加相应的游戏分值。可是,所有地鼠只会在地上出现一段时间(而且消失后再也不会出现),每个地鼠都在0时刻冒出,但停留的时间可能是不同的,而且每个地鼠被敲击后增加的游戏分值也可能是不同。
最近2320学长经常玩这个游戏,以至于敲击每个地鼠只要1秒。他在想如何敲击能使总分最大。
输入描述:
输入包含3行,第一行包含一个整数n(1<=n<=100000)表示有n个地鼠从地上冒出来,第二行n个用空格分隔的整数表示每个地鼠冒出后停留的时间(Maxt<=50000),第三行n个用空格分隔的整数表示每个地鼠被敲击后会增加的分值v(v<=1000)。每行中第i个数都表示第i个地鼠的信息。
样例输入:
5
5 3 6 1 4
7 9 2 1 5
样例输出:
24
数据范围:
30%的数据保证n<=100, t<=500,v<=50
60%的数据保证 n<=10000,t<=3000,v<=500
100%的数据保证 n<=100000,t<=5000,v<=1000
【题解】
嗯。。我太弱辣,居然没有一眼看出贪心策略
把时间限制从大到小排列
从大到小扫时间
把当前时间点的地鼠压入堆
每个时间点从堆中取最大值
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <queue> 6 #include <algorithm> 7 #include <vector> 8 #define max(a, b) ((a) > (b) ? (a) : (b)) 9 10 inline void read(int &x) 11 { 12 x = 0;char ch = getchar(), c = ch; 13 while(ch < '0' || ch > '9')c = ch, ch = getchar(); 14 while(ch <= '9' && ch >= '0')x = x * 10 + ch - '0', ch = getchar(); 15 if(c == '-')x = -x; 16 } 17 18 const int MAXN = 100000 + 10; 19 20 int n, ma, ans; 21 22 struct Node 23 { 24 int v,t; 25 }node[MAXN]; 26 27 bool cmp(Node a, Node b) 28 { 29 return a.t > b.t; 30 } 31 32 struct cmpp 33 { 34 bool operator()(Node a, Node b) 35 { 36 return a.v < b.v; 37 } 38 }; 39 40 std::priority_queue<Node, std::vector<Node>, cmpp> q; 41 42 int main() 43 { 44 read(n); 45 for(register int i = 1;i <= n;++ i) 46 read(node[i].t), ma = max(ma, node[i].t); 47 for(register int i = 1;i <= n;++ i) 48 read(node[i].v); 49 std::sort(node + 1, node + 1 + n, cmp); 50 register Node tmp; 51 node[n + 1].t = 0x7fffffff; 52 for(register int now = ma, i = 1;now >= 1;-- now) 53 { 54 while(node[i].t == now) 55 { 56 q.push(node[i]); 57 ++ i; 58 } 59 if(q.size()) 60 { 61 tmp = q.top(); 62 ans += tmp.v; 63 q.pop(); 64 } 65 } 66 printf("%d", ans); 67 return 0; 68 }
斗牛
(niuniu.pas/.c/.cpp)
时间限制:2s,空间限制:128MB
题目描述:
为了更快的获取欢乐豆(因为本蒟蒻斗地主水平太低233),hzwer准备去玩欢乐斗牛,但是由于rp太差,hzwer在一个小时之内输光了20个QQ号的欢乐豆(每天系统会赠送每个号4000欢乐豆)。第二天他准备继续再战欢乐斗牛的抢庄模式,但是由于缺乏思考能力,hzwer需要编写一个程序来决定是否抢庄。
在玩家决定是否抢庄之前,系统会下发四张牌称为底牌,最后一张牌在决定后发放,每张牌可能为1-10,J,Q,K,hzwer认为最后一张牌为每一种点数的概率是相同的,对于一个由五张牌组成的牌型,分数计算规则如下,请你得出底牌的期望得分。
首先注意:在斗牛中,J,Q,K的点数视为10点,即11,12,13在计算头或点数时均视为10,所有牌无视其花色。
首先考虑特殊牌型
- 四炸——即5张牌中有4张一样的牌(如33334),分数为40
- 五花牛——五张牌均是J,Q或K(如JQJQK),分数为50
- 五小牛——五张牌点数都小于5且点数和小于或等于10(如11223),分数为60
若有多种特殊牌型,得分取分数最大的特殊牌型(如11112视为五小牛)。
如果没有特殊牌型,首先判断牌型是否有“头”,如果五张牌中任意三张的总和为10的倍数如(1K9)即为有“头”,无“头”的牌型得分为0。
对于有头的牌型得分计算如下:
所有牌的和记为t,如果t%10=0则称为“牛牛”,牛牛得分为30;t%10<7称为“小牛”,得分为t%10,否则得分为(t%10)*2。
输入描述:
第一行一个整数T,表示T组数据
每组数据占一行,为4个整数(11,12,13分别表示J,Q,K)
输出描述:
对于输入的n行,输出每4张牌的期望得分(四舍五入)
样例输入:
2
2 2 2 2
10 4 5 12
样例输出:
43
9
样例解释:
对于2 2 2 2,最后一张为1或2时,构成五小牛,否则为炸弹,期望得分为(2*60+11*40)/13=43.08
对于10 4 5 12,最后一张为1-13的得分分别是30+0+0+0+4+5+0+0+0+18+18+18+18=111/13=8.54
1为牛牛,5为4点,6为5点,10-13为9点,其余无头
数据范围:
30%的数据T<=5
70%的数据T<=100000
100%的数据T<=1000000
蒟蒻感言:
在某次对局中发现期望得分很高,果断抢了庄,但是发现有闲家3个“牛牛”,瞬间消失20W欢乐豆
【题解】
我太弱辣。。这种题居然还得调一会儿才能调对,应该是一遍过的啊
情况数*10~询问数
所以预处理所有情况即可
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #define min(a, b) ((a) < (b) ? (a) : (b)) 6 7 inline void read(int &x) 8 { 9 x = 0;char ch = getchar(), c = ch; 10 while(ch < '0' || ch > '9')c = ch, ch = getchar(); 11 while(ch <= '9' && ch >= '0')x = x * 10 + ch - '0', ch = getchar(); 12 if(c == '-')x = -x; 13 } 14 15 int num[6],ans[14][14][14][14][14]; 16 17 int main() 18 { 19 register int t; 20 read(t); 21 register int sum,a,b,c,d,e,ta,tb,tc,td,te; 22 for(a = 1;a <= 13;++ a) 23 for(b = 1;b <= 13;++ b) 24 for(c = 1;c <= 13;++ c) 25 for(d = 1;d <= 13;++ d) 26 for(e = 1;e <= 13;++ e) 27 { 28 if(a < 5 && b < 5 && c < 5 && d < 5 && e < 5 && a + b + c + d + e <= 10) 29 { 30 ans[a][b][c][d][e] = 60; 31 } 32 else if(a > 10 && b > 10 && c > 10 && d > 10 && e > 10) 33 { 34 ans[a][b][c][d][e] = 50; 35 } 36 else if((a == b&&b==c&&c==d) || (a==b&&b==c&&c==e) || (a==b&&b==d&&d==e) || (b==c&&c==d&&d==e) || (a==c&&c==d&&d==e)) 37 { 38 ans[a][b][c][d][e] = 40; 39 } 40 else 41 { 42 ta = min(10, a), tb = min(10, b), tc = min(10, c), td = min(10, d), te = min(10, e); 43 if((ta + tb + tc)%10 == 0 || (ta + tb + td)%10 == 0 || (ta + tb + te)%10 == 0 || (tb + tc + td)%10 == 0 || (tb + tc + te)%10 == 0 || (ta + tc + td)%10 == 0 || (ta + tc + te)%10 == 0 || (ta + td + te)%10 == 0 || (tb + td + te)%10 == 0 || (tc + td + te)%10 == 0) 44 { 45 sum = ta + tb + tc + td + te; 46 if(sum%10 == 0) ans[a][b][c][d][e] = 30; 47 else if(sum%10 < 7)ans[a][b][c][d][e] = sum%10; 48 else ans[a][b][c][d][e] = (sum%10)*2; 49 } 50 else 51 { 52 ans[a][b][c][d][e] = 0; 53 } 54 } 55 } 56 for(;t;--t) 57 { 58 read(num[1]),read(num[2]),read(num[3]),read(num[4]); 59 sum = 0; 60 for(register int i = 1;i <= 13;++ i) 61 { 62 num[5] = i; 63 sum += ans[num[1]][num[2]][num[3]][num[4]][num[5]]; 64 } 65 sum = (sum/13.0) + 0.5; 66 printf("%d\n", sum); 67 } 68 return 0; 69 }