2017 11.6 NOIP模拟赛
1.数学老师的报复
(attack.pas/c/cpp)
【问题描述】
11 班数学大佬 YXN 又在上数学课的时候把班主任 MP6 的错误当众挑出来了,MP6 再一
次感到很难堪,于是决定报复 YXN
MP6 对 YXN 说:给你一个函数 f(x),定义如下:
f ( 1 ) = 1
f ( 2 ) = 1
f ( n ) = ( A * f ( n - 1 ) + B * f ( n - 2 ) ) mod 7。
YXN 说这还不简单,可以秒杀!
MP6 微微笑了笑说:n 等于 100 你算得出来,那 n 等于 2147483648 呢?
YXN 哑口无言,决定向信息组的你求助。由于这是你唯一一次可以在数学题上秒杀 YXN,
你决定好好把握这一次机会。
【输入】
仅一行包含 3 个整数 A,B 和 n。
【输出】
一个整数,即 f ( n ) 的值。
【输入输出样例】
样例 1 样例 2
attack.in attack.out attack.in attack.out
1 1 3
2
1 2 10
5
【数据说明】
20%的数据, n≤1,000
50%的数据, n≤100,000,000
100%的数据,n≤2147,483,648
思路 :矩阵快速幂加速加速
转置矩阵为 A 1
B 0
跑快速幂就好了
但是我一开始是骗分做的
因为 7 是一个很小的数 它的循环节不会很长
每次找出循环节的长度即可。
1 #include<bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 ll n,aa,bb; 5 struct matrix{ 6 ll a[2][2]; 7 matrix(){memset(a,0,sizeof(a));} 8 matrix(ll b[2][2]) {for(int i=0;i<2;i++)for(int j=0;j<2;j++)a[i][j]=b[i][j];} 9 matrix operator * (matrix b) 10 { 11 matrix ans; 12 for(int i=0;i<2;i++) 13 for(int j=0;j<2;j++) 14 for(int k=0;k<2;k++) 15 ans.a[i][j]=(ans.a[i][j]+a[i][k]*b.a[k][j])%7; 16 ans.a[0][0]%=7; 17 return ans; 18 } 19 }S,T; 20 21 inline ll read() 22 { 23 ll x=0,f=1;char c=getchar(); 24 while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} 25 while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} 26 return x*f; 27 } 28 29 int main() 30 { 31 freopen("attack.in","r",stdin); 32 freopen("attack.out","w",stdout); 33 while(scanf("%lld%lld%lld",&aa,&bb,&n)!=EOF) 34 { 35 n-=2; 36 if(n==-1) {printf("1");return 0;} 37 ll temp[2][2]={{aa,1},{bb,0}}; T=temp; 38 ll temp2[2][2]={{1,1},{0,0}}; S=temp2; 39 while(n) 40 { 41 if(n&1) S=S*T; 42 T=T*T; 43 n>>=1; 44 } 45 S.a[0][0]%=7; 46 printf("%lld",S.a[0][0]); 47 } 48 return 0; 49 }
1 #include <cctype> 2 #include <cstdio> 3 4 const int MAXN = 100010; 5 6 typedef long long LL; 7 8 int A, B; 9 10 LL n; 11 12 inline void read(int&x) { 13 int f = 1; register char c = getchar(); 14 for(x = 0; !isdigit(c); c == '-'&&(f = -1), c=getchar()); 15 for(; isdigit(c); x = x * 10 + c - 48, c = getchar()); 16 x = x * f; 17 } 18 19 inline void read(LL&x) { 20 int f = 1; register char c = getchar(); 21 for(x = 0; !isdigit(c); c == '-'&&(f = -1), c=getchar()); 22 for(; isdigit(c); x = x * 10 + c - 48, c = getchar()); 23 x = x * f; 24 } 25 26 namespace stepone { 27 int F[1010]; 28 inline void vinlince() { 29 F[1] = 1; F[2] = 1; 30 for(int i = 3; i <= n; ++i) 31 F[i] = (A * F[i - 1] + B * F[i - 2]) % 7; 32 printf("%d\n", F[n]); 33 return; 34 } 35 } 36 37 namespace steptwo { 38 int F[1010], pos; 39 inline void vinlince() { 40 if(A % 7 ==0) { 41 if(n >= 3) printf("0\n"); 42 else printf("1\n"); 43 return; 44 } 45 F[1] = 1; F[2] = 1; 46 for(int i = 3; i <= 1010; ++i) { 47 F[i] = (A * F[i - 1] + B * F[i - 2]) % 7; 48 if(F[i] == 1) { 49 pos = i; 50 break; 51 } 52 } 53 pos -= 2; --n; 54 n %= pos; 55 if(n == 0) n = pos; 56 printf("%d\n", F[n + 1]); 57 return; 58 } 59 } 60 61 namespace stepthree { 62 int F[1010], pos; 63 inline void hhh() { 64 F[1] = 1; F[2] = 1; 65 for(int i = 3; i <= 1010; ++i) { 66 F[i] = (A * F[i - 1] + B * F[i - 2]) % 7; 67 if(F[i] == 1 && F[i - 1] == 1) { 68 pos = i - 1; 69 break; 70 } 71 } 72 --pos; 73 n %= pos; 74 if(n == 0) n = pos; 75 printf("%d\n", F[n]); 76 return; 77 } 78 } 79 80 int main(int argc,char**argv) { 81 freopen("attack.in", "r", stdin); 82 freopen("attack.out", "w", stdout); 83 84 read(A), read(B), read(n); 85 if(n <= 1000) stepone::vinlince(); 86 else if(B % 7 == 0) steptwo::vinlince(); 87 else stepthree::hhh(); 88 89 return 0; 90 }
2.物理和生物老师的战争
(fseq.pas/c/cpp)
【问题描述】
物。万物也。牛为大物。牛为物之大者。故物从牛。与半同意。天地之数起於牵
牛。戴先生原象曰。牵牛为纪首。命曰星纪。自周而上。日月之行不起於;牵牛也。按许说
物从牛之故。又广其义如此。故从牛。勿声。文弗切。十五部。
总之,物理老师和生物老师因为“物”而吵了起来,物理老师认为,物理是万物之
源, 而生物老师认为生物才是万物之源。 所以物理学科带头人和生物学科带头人号召了所有
物理、生物老师,进行战斗。
战斗开始前他们需要排队,有 n 个物理老师和 m 个生物老师站在一起排成一列,
过安检进入打斗场。物理老师是一个神奇的物种,他们十分严谨,在开始之前就分析过:如
果在任意某一个人往前数(包括这个人) ,生物老师的数量超过了物理老师,根据牛顿三大
定律以及开普勒三大定律,这样风水是不太好的。这时候,物理老师就会引爆核弹。为了构
建社会主义和谐社会,你决定避免这一场核战的发生。所以,请你计算不会引发核弹爆炸的
排队方案的概率。 (排队方案不同定义为当且仅当某一位老师不一样,注意不是老师所教的
科目不一样。eg:物 A 物 B,物 B 物 A,是不同的方案)
【输入】
第一行,Test , 表示测试数据的组数。
每个数据 有两个数 N,M
【 输出】
对于每组数据,输出一个实数(保留到小数点后 6 位,)
【输入输出样例 1】
fseq.in fseq.out 样例说明:
3
1 0
0 1
1 1
1.000000
0.000000
0.500000
第一行:只有一个物理老师,一种方案且可行
第二行:只有一个生物老师,一种方案且不可行
第三行:两种方案 ① 理、生 可行
② 生、理 不可行 可行概率为 0.5
【数据范围】
30%的数据:(Test<=10),(0<=N,M<=1000).
100%的数据:(Test<=9008 ),( 0<=N,M<=20000 ).
思路:卡特兰数应用 组合数学 进栈为题
大家 可以去 这里看一下 讲的听好的
方案数 为 C(m!, (n+m)!) - C((m-1)!, (n+m)!)
可以化出 (m+n)!/m!*n! *(1-m/(n+1))
整个式子表示可行方案数 那后面的不就是可行的概率了么。。
1 #include <map> 2 #include <cstdio> 3 #include <cctype> 4 #define min(x,y) ((x) < (y) ? (x) : (y)) 5 6 const int MAXN = 5010; 7 8 int T, n, m; 9 10 inline void read(int&x) { 11 int f = 1; register char c = getchar(); 12 for(x = 0; !isdigit(c); c == '-'&&(f = -1), c=getchar()); 13 for(; isdigit(c); x = x * 10 + c - 48, c = getchar()); 14 x = x * f; 15 } 16 17 int main(int argc,char**argv) { 18 freopen("fseq.in", "r", stdin); 19 freopen("fseq.out", "w", stdout); 20 21 read(T); 22 while(T--) { 23 read(n);read(m); 24 if(n < m) printf("0.000000\n"); 25 else printf("%.6lf\n",1.0-(m*1.0/(n + 1.0))); 26 } 27 return 0; 28 }
3.化学竞赛的大奖
(prize.pas/c/cpp)
【问题描述】
XYX 在 CChO(全国化学奥林匹克竞赛)比赛中获得了大奖,奖品是一张特殊的机票。
使用这张机票,可以在任意一个国家内的任意城市之间的免费飞行,只有跨国飞行时才
会有额外的费用。XYX 获得了一张地图,地图上有城市之间的飞机航班和费用。已知从
每个城市出发能到达所有城市,两个城市之间可能有不止一个航班。一个国家内的每两
个城市之间一定有不止一条飞行路线, 而两个国家的城市之间只 有一条飞行路线。 XYX
想知道, 从每个城市出发到额外费用最大的城市, 以便估算出出行的费用, 请你帮助他。
当然,你不能通过乘坐多次一个航班增加额外费用, 也就是必须沿费用最少的路线飞
行。
【输入】
第一行,两个整数 N,M,表示地图上有 N 个城市,M 条航线。
接下来 M 行,每行三个整数 a,b,c,表示城市 a,b 之间有一条费用为 c 的航线。
【 输出】
共 N 行,第 i 行为从城市 i 出发到达每个城市额外费用的最大值。
【输入输出样例 1】
score.in score.out 样例说明:
6 6
1 4 2
1 2 6
2 5 3
2 3 7
6 3 4
3 1 8
4
4
4
6
7
7
有四个国家,包含的城市分别为 {1,2,3},{4},{5},{6}。
从城市 1 出发到达城市 6,乘坐(1,3)(3,6)两个航班费用最大,
(1,3)在国内为免费航班,(3,6)的费用为 4,所以从 1 出发的最
大费用为 4。
【数据范围】
对于 40%的数据 1<=N<=1000,1<=M<=1000
对于 100%的数据 1<=N<=20000,1<=M<=200000
思路 :首先 Tarjan 缩点
建新图 新图一定为 树
求一点能到达的点的路径权值和最大
跑 三遍DFS 或 用树形Dp即可
1 #include <vector> 2 #include <cstdio> 3 #include <cctype> 4 #include <cstring> 5 #define max(x,y) ((x) < (y) ? (y) : (x)) 6 #define min(x,y) ((x) < (y) ? (x) : (y)) 7 8 const int MAXN = 20010; 9 10 int n, m, inr, top, tot; 11 12 int dfn[MAXN], low[MAXN], stack[MAXN << 1], col[MAXN], x[200010], y[200010], z[200010]; 13 14 int q[MAXN<<2], dis[MAXN], _dis[MAXN]; 15 16 std::vector<int> Graph[MAXN]; 17 18 bool vis[MAXN]; 19 20 struct node { 21 int to, val; 22 node(){} 23 node(int to, int val):to(to), val(val){} 24 }; 25 26 std::vector<node> New[MAXN]; 27 28 inline void read(int&x) { 29 int f = 1; register char c = getchar(); 30 for(x = 0; !isdigit(c); c == '-'&&(f = -1), c=getchar()); 31 for(; isdigit(c); x = x * 10 + c - 48, c = getchar()); 32 x = x * f; 33 } 34 35 namespace Tarjan { 36 37 void tarjan(int u, int fa) { 38 dfn[u] = low[u] = ++inr; 39 stack[++top] = u; 40 vis[u] = true; 41 for(int i = 0; i <Graph[u].size(); ++i) { 42 int v = Graph[u][i]; 43 if(v == fa) continue; 44 if(!dfn[v]) { 45 tarjan(v, u); 46 low[u] = min(low[u], low[v]); 47 } 48 else if(vis[v]) low[u] = min(low[u], dfn[v]); 49 } 50 51 if(dfn[u] == low[u]) { 52 ++tot; 53 int t; 54 do { 55 t = stack[top--]; 56 vis[t] = false; 57 col[t] = tot; 58 }while(u != t); 59 } 60 return; 61 } 62 63 void Pre() { 64 for(int i = 1; i <= m; ++i) { 65 read(x[i]); read(y[i]); read(z[i]); 66 Graph[x[i]].push_back(y[i]); 67 Graph[y[i]].push_back(x[i]); 68 } 69 70 for(int i = 1; i <= n; ++i) 71 if(!dfn[i]) tarjan(i, -1); 72 return; 73 } 74 } 75 76 namespace _next { 77 int Max, root; 78 79 void DFS(int u,int fa) { 80 for(int i = 0; i < New[u].size(); ++i) { 81 int v = New[u][i].to; 82 if(v == fa) continue; 83 dis[v] = dis[u] + New[u][i].val; 84 if(dis[v] > Max) Max = dis[v], root = v; 85 DFS(v, u); 86 } 87 return; 88 } 89 90 void _DFS(int u,int fa) { 91 for(int i = 0; i < New[u].size(); ++i) { 92 int v = New[u][i].to; 93 if(v == fa) continue; 94 _dis[v] = _dis[u] + New[u][i].val; 95 _DFS(v, u); 96 } 97 return; 98 } 99 100 void hhh() { 101 102 for(int i = 1; i <= m; ++i) { 103 if(col[x[i]] != col[y[i]]) { 104 New[col[x[i]]].push_back(node(col[y[i]], z[i])); 105 New[col[y[i]]].push_back(node(col[x[i]], z[i])); 106 } 107 } 108 109 DFS(1,-1); 110 Max = 0; 111 memset(dis, 0, sizeof dis); 112 DFS(root, -1); 113 _DFS(root, -1); 114 115 for(int i = 1; i <= n; ++i) 116 printf("%d\n", max(dis[col[i]], _dis[col[i]])); 117 return; 118 } 119 } 120 121 int main(int argc,char**argv) { 122 freopen("prize.in", "r", stdin); 123 freopen("prize.out", "w", stdout); 124 125 read(n), read(m); 126 Tarjan::Pre(); 127 _next::hhh(); 128 129 return 0; 130 }
作者:乌鸦坐飞机
出处:http://www.cnblogs.com/whistle13326/
新的风暴已经出现
怎么能够停止不前
穿越时空 竭尽全力
我会来到你身边
微笑面对危险
梦想成真不会遥远
鼓起勇气 坚定向前
奇迹一定会出现