zoukankan      html  css  js  c++  java
  • 6.13 模拟赛结题报告

    写在前面

    二区教练:啊培训了这么多天,我和三区教练决定出套题来考试。

    然后他妈的搬了 HN 某中学某学生出的题,还他妈和培训内容屁关系没有。

    笑了。

    预期:100 + 100 + 40 = 240

    实际:15 + 100 + 20 = 135

    开题顺序 1 3 2。

    T1 是矩阵板子,开场五分钟样例过了就扔了,结果 n-1 写成 n 多跑了一次快速幂导致挂 85 分。我是傻逼。

    后来问了问同样挂 T1 的 zzg,发现他是少跑了一次快速幂,笑死。

    /cy

    T2 首先想到是个 (O(1)) 结论题,然后开始人工打表找规律,结果开始看错题,找了一个半小时才结束。

    /cy

    T3 打的部分分,正解想到了但是以为只能 DP 做,结果还写挂了。

    /cy

    caq AK orz.

    所以我就是次次模拟赛挂 T1 的神!

    这个故事告诉我们,男人不能太自信。

    []

    正文

    T1

    (f[1]=f[2]=1)
    (f[n]=(A imes f[n-1]+B imes f[n-2])mod 7)
    给定 (A,B,n),求 (f[n])
    (nle 21,4748,3648。)

    “这个模数小,肯定有诈啊!”——szt。

    做法 1:矩阵板子直接上就行了。注意模数小,所以样例不可信啊!!!

    做法 2:模数小,手模几个数可以发现,答案是一个周期函数,然后求就可以。

    我也猜到了与周期有关,但是感觉没有写矩阵来的实在。

    #include<queue>
    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define maxn 100010 
    #define INF 0x3f3f3f3f
    #define int long long
    #define Mod 7
    
    using namespace std;
    
    int A,B,n;
    
    struct Matrix{
      int z[20][20];
      Matrix(){memset(z,0,sizeof z);}
      Matrix operator * (const Matrix &b){
        Matrix ans;
        for(int i=1;i<=2;i++)
          for(int j=1;j<=2;j++)
            for(int k=1;k<=2;k++)
              ans.z[i][k]=(ans.z[i][k]+(z[i][j]%Mod)*(b.z[j][k]%Mod))%Mod;
        return ans;
      }
    }jz,res,all;
    
    int read(){
      int s=0,w=1;char ch=getchar();
      while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
      while(ch>='0'&&ch<='9')s=(s<<1)+(s<<3)+ch-'0',ch=getchar();
      return s*w;
    }
    
    void quickpow(int y){
      while(y){
        if(y&1) res=res*jz;
        jz=jz*jz;y>>=1;
      }
    }
    
    signed main(){
    //  freopen("attack.in","r",stdin);
    //  freopen("attack.out","w",stdout);
      A=read();B=read();n=read();
      jz.z[1][1]=A;jz.z[1][2]=1;jz.z[2][1]=B;
      res.z[1][1]=res.z[1][1]=1;
      quickpow(n-1);printf("%lld
    ",res.z[1][2]);
      return 0;
    }
    
    

    T2

    我草图片怎么这么大。

    (T) 组询问,(Tle 9008,0le n,mle 20000.)

    啊这个 (O(nT)) 的复杂度都过不了,那这个肯定是 (O(1)) 出答案。

    要不来猜结论?一开始看错题,看成 从第 (i) 个人开始往前到每一个位置物理老师都不能小于生物老师。

    怀疑题目出错了,感觉这显然不可做啊。后来发现读错题了,推出个 (large{frac{(2 imes m + 1)}{(m+n)!}^{(n-m)}}) 感觉蛮对的,但是 (O(1)) 搞不了。

    于是大力打表,搞了 6 + 24 + 120 + 720 = 870 种情况。发现结果如下:

    瞪眼法找规律 
    n m -> ans
    1 0 -> 1
    1 1 -> 1/2
    2 1 -> 4/6 = 2/3
    2 2 -> 8/24 = 1/3
    3 1 -> 18/24 = 3/4 
    3 2 -> 60/120 = 2/4
    3 3 -> 180/720 = 1/4
    

    我估计不是傻逼都能看出来吧。答案是 (large{frac{n-m+1}{n+1}})

    然后讲讲怎么想出来。

    可以将原问题转化一下,看成是在一个二维平面上行走,物理老师看成移动 ((1,0)),生物老师看成移动 ((0,1))
    那么到达 ((n,m)) 点且路线又不走到 (y=x) 这条直线上方的路线总数就是答案。
    这个组合问题很经典,方案数为 (egin{pmatrix} m+n\ m end{pmatrix} - egin{pmatrix} m+n \ m-1 end{pmatrix})
    化简完答案同上。

    核心代码就一行,就不放了。

    T3

    给出 (n) 个点,(m) 条带权双向边,假设同一个双联通分量中的点不计边权,问每个点到其他点的最远距离。
    (1le nle 20000,1le mle 200000)

    首先想到双联通分量缩点,然后考虑怎么找最长。

    发现缩完后是一棵树,然后决定跑最短路(雾。其实是想先拿前四十分的。结果最后 T2 写完就到点了。

    szt 表示可以跑树剖 + 树形 DP + 换根,我直接问号。

    其实有想到是求树的直径两点中较远的那个,但是以为 dfs 求也过不了,DP 又没自信写,就这么过去了。

    然后发现 AK 神 caq dfs 过了。

    好了扯远了。这题其实只要 dfs/DP 出树的直径的两个点 (a,b),然后答案就是 (max(dis_{a,x},dis_{b,x}))

    就没了。

    #include<queue>
    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define maxn 2001000
    #define INF 0x3f3f3f3f
    //#define int long long
    
    using namespace std;
    
    bool vis[maxn];
    int n,tot=1,cnt,top,t,m,TOT,Max,rt;
    int num[maxn],val[maxn],Head[maxn];
    int low[maxn],head[maxn],ans[maxn],Ans[maxn];
    int Dis[maxn][3],siz[maxn],zhan[maxn],dfn[maxn];
    struct edge{int fr,to,dis,nxt;}e[maxn*20],E[maxn*20];
    
    int read(){
      int s=0,w=1;char ch=getchar();
      while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
      while(ch>='0'&&ch<='9')s=(s<<1)+(s<<3)+ch-'0',ch=getchar();
      return s*w;
    }
    
    void add(int fr,int to,int dis){
      e[++tot].fr=fr;e[tot].to=to;e[tot].dis=dis;
      e[tot].nxt=head[fr];head[fr]=tot;
    }
    
    void Add(int fr,int to,int dis){
      E[++TOT].fr=fr;E[TOT].to=to;
      E[TOT].dis=dis;E[TOT].nxt=Head[fr];
      Head[fr]=TOT;
    }
    
    void tarjan(int u){
      low[u]=dfn[u]=++cnt;
      zhan[++top]=u;
      for(int i=head[u];i;i=e[i].nxt){
        if(!vis[i]){
          vis[i]=vis[i^1]=1;int to=e[i].to;
          if(!dfn[to]) tarjan(to),low[u]=min(low[u],low[to]);
          else low[u]=min(low[u],dfn[to]);
        }
      }
      if(dfn[u]==low[u]){
        ++siz[++t];
        int pre=zhan[top--];
        num[pre]=t;
        while(pre!=u){
          ++siz[t];
          pre=zhan[top--];
          num[pre]=t;
        }
      }
    }
    
    void dfs1(int u,int fa){
      for(int i=Head[u];i;i=E[i].nxt){
        int to=E[i].to;
        if(to==fa) continue;
        Dis[to][1]=Dis[u][1]+E[i].dis;
        if(Dis[to][1]>Max) Max=Dis[to][1],rt=to;
        dfs1(to,u);
      }
    }
    
    void dfs2(int u,int fa){
      for(int i=Head[u];i;i=E[i].nxt){
        int to=E[i].to;
        if(to==fa) continue;
        Dis[to][2]=Dis[u][2]+E[i].dis;
        dfs2(to,u);
      }
    }
    
    int main(){
    //  freopen("prize2.in","r",stdin);
    //  freopen("prize.out","w",stdout);
      n=read();m=read();
      for(int i=1,fr,to,dis;i<=m;i++){
        fr=read();to=read();dis=read();
        add(fr,to,dis);add(to,fr,dis);
      }
      for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i);
      for(int i=1;i<=n;i++)
        for(int j=head[i];j;j=e[j].nxt){
          int to=e[j].to;
          if(num[i]!=num[to]) Add(num[i],num[to],e[j].dis);
        }  
      dfs1(1,-1);memset(Dis,0,sizeof Dis);Max=0;
      dfs1(rt,-1);Max=0;dfs2(rt,-1);
      for(int i=1;i<=n;i++)
        printf("%d
    ",max(Dis[num[i]][1],Dis[num[i]][2]));
      return 0;
    }
    

    []

    写在后面

    自信 + 不自信 + 菜 + naive 是这次挂分的原因。

    还是需要多练啊/kk。

    以后看到这个傻逼记得提醒他检查 T1。

  • 相关阅读:
    为什么全局变量一定要初始化?
    SecureCRT 使用密钥登录 Ubuntu
    ubuntu samba 服务器搭建
    Linux 软硬链接的区别及目录权限对软硬链接的影响
    【转载】解析 java 按值传递还是按引用传递
    (转)如何学好C语言
    (转)五个方法成为更好的程序员
    (转)SQLite数据库的加密
    鸟哥Linux私房菜(基础篇)——第十一章:认识与学习Bash
    鸟哥Linux私房菜(基础篇)——第五章:首次登入与在线求助 man page笔记
  • 原文地址:https://www.cnblogs.com/KnightL/p/14881906.html
Copyright © 2011-2022 走看看