zoukankan      html  css  js  c++  java
  • 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
    ", 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
    ");
    42             else printf("1
    ");
    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
    ", 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
    ", 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
    ");
    25         else printf("%.6lf
    ",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
    ", 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 }
    代码
  • 相关阅读:
    图论基础
    降维和聚类系列(二):拉普拉斯特征映射Laplacian Eigenmaps,谱聚类,实例代码
    降维和聚类系列(一):方法综述和比较(持续更新中)
    markdown设置图片尺寸
    指示向量indicator vector
    Sherlock and his girlfriend CodeForces
    The Meeting Place Cannot Be Changed CodeForces
    The Meeting Place Cannot Be Changed CodeForces
    数组分块入门 3
    数组分块入门 3
  • 原文地址:https://www.cnblogs.com/whistle13326/p/7800764.html
Copyright © 2011-2022 走看看