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 }

代码

时间: 2024-10-10 00:22:25

2017 11.6 NOIP模拟赛的相关文章

2017.9.24 noip模拟赛 day2—组合数

简化版题意: 给定n,m(n<=m),求C(n,m)的末尾有几个0 输入格式: 第一行一个整数t,代表数据组数. 接下来t行,每行两个整数n,m 输出格式: t行,每行一个整数,代表C(n,m)的末尾0的个数. 样例输入: 310 111 720 4 样例输出: 110 数据范围: 1<=m<=n<=1000000,t<=1000 首先这道题需要知道一个公式:C(n,m)=n!/(n-m)!*m! 然后10=2*5,也就是说,对于一个数,我们将其因数分解,2和5中较少的数的个

2017 9 15 noip模拟赛

t1: #include<cstdio> #include<cstring> const int N=1000010; int a[N],b[N]; int sum=1,maxx=0; int main() { freopen("sequence.in","r",stdin); freopen("sequence.out","w",stdout); int n; scanf("%d"

2017.5.27 NOIP模拟赛(hzwer2014-5-16 NOIP模拟赛)

期望得分:100+100+60+30=290 实际得分:100+20+60+0=180 当务之急:提高一次正确率 Problem 1 双色球(ball.cpp/c/pas) [题目描述] 机房来了新一届的学弟学妹,邪恶的chenzeyu97发现一位学弟与他同名,于是他当起了善良的学长233 “来来来,学弟,我考你道水题检验一下你的水平……” 一个栈内初始有n个红色和蓝色的小球,请你按照以下规则进行操作 只要栈顶的小球是红色的,将其取出,直到栈顶的球是蓝色 然后将栈顶的蓝球变成红色 最后放入若干个

2017 9 11 noip模拟赛T2

#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=205; int map[N][N]; int d[N],tag[N],book[N],f[N]; int n,m; void work(int x) { memset(d,63,sizeof(d)); memset(book,0,sizeof(book)); memset(f,0,sizeof(

【简单思考】noip模拟赛 NTR酋长

NTR酋长 (ntr.pas/.c/.cpp) 黄巨大终于如愿以偿的进入了czy的后宫中……但是czy很生气……他要在黄巨大走到他面前的必经之路上放上几个NTR酋长来阻挡黄巨大. 众所周知,NTR酋长有一个技能是沟壑(F).它会在地图上产生一条长长的障碍物阻挡人前进.Czy打算在一个n*m的矩形(必经之路?)中放上NTR酋长.NTR酋长要一个一个放下去,而且每放一个都会向四角倾斜的方向放出无限长的沟壑,而已经被沟壑挡住的地方就不能再放NTR酋长了. 请注意:不会出现沟壑的路径挡住另一个沟壑的情况

NOIP模拟赛 6.29

2017-6-29 NOIP模拟赛 Problem 1 机器人(robot.cpp/c/pas) [题目描述] 早苗入手了最新的Gundam模型.最新款自然有着与以往不同的功能,那就是它能够自动行走,厉害吧. 早苗的新模型可以按照输入的命令进行移动,命令包括‘E’.‘S’.‘W’.‘N’四种,分别对应东南西北.执行某个命令时,它会向对应方向移动一个单位.作为新型机器人,它可以执行命令串.对于输入的命令串,每一秒它会按命令行动一次.执行完命令串的最后一个命令后,会自动从头开始循环.在0时刻时机器人

【noip模拟赛4】Matrix67的派对 暴力dfs

[noip模拟赛4]Matrix67的派对 描述 Matrix67发现身高接近的人似乎更合得来.Matrix67举办的派对共有N(1<=N<=10)个人参加,Matrix67需要把他们安排在圆桌上.Matrix67的安排原则是,圆桌上任意两个相邻人的身高之差不能超过K.请告诉Matrix67他共有多少种安排方法. 输入 第一行输入两个用空格隔开的数N和K,其中1<=N<=10,1<=K<=1 000 000. 第二行到第N+1行每行输入一个人的身高值.所有人的身高都是不

【noip模拟赛】 射击

这题似乎是什么安阳一中的模拟题,不管了,反正是学长出的noip模拟赛里面的题目.... 射击(shoot.pas/.c/.cpp) 时间限制:1s,内存限制128MB 题目描述: 据史书记载,对越反击战时期,有位中国侦察兵,他的代号叫814.一天他执行狙击任务,他的任务地区是n座恰巧在一条直线上的山.这些山所在直线恰巧为东西走向,山从东到西依次编号为1~n.一天814隐藏在编号为k的山上,每座山上都有1个目标. 814也非常的厉害,任务结束时杀了很多人,可是史书中只记载了两点: 1:814一定攻

NOIP模拟赛

#1[Nescafé 31]杯NOIP模拟赛 t1 题意:n*m的棋盘上从(1,1)走到(n,m),只能向下或向右,一些格子有老鼠,每个老鼠互不相同,当处于与老鼠有重边的格子时,视为看见了这只老鼠,求到终点看到最少的不同老鼠数. 分析:DP 由于求得是看到的不同的老鼠数目,不能直接用过河卒做,因为同一个位置的老鼠可能会统计多次,我们还需要增加一维即方向. f[i,j,0]表示到从上面一个格子走到(i,j)时最少老鼠数,f[i,j,1]表示左边. f[i,j,0]:=min(f[i-1,j,0]+