• ATP学姐的模拟赛


      ATPの水题大赛

      声明:不是我觉得这题水,这就是本场模拟赛的名称。

      T1:求所有的$n$位数中有几个数满足:每一位要么是$A$要么是$B$,并且这个$n$位数的每一位加起来是$A$或$B$的倍数。

      $n<=100000,0<A,B<=9$且$A$与$B$不相等

      因为昨天刚讲了数位$dp$,理所当然的就往那方面去想了.其实用组合数学也可以做,而且还比较简短.

      用$f[i][j][k]$表示目前填到第$i$位,对$a$取模余数为$j$,对$b$取模余数为$k$的方案数.滚动数组,空间可以压得非常小.

      
     1 # include <cstdio>
     2 # include <iostream>
     3 # include <cstring>
     4 # include <string>
     5 # define R register int
     6 # define mod 1000000007
     7 
     8 using namespace std;
     9 
    10 const int maxn=100005;
    11 int dp[3][10][10];
    12 int a,b,n,ans,no,nex;
    13 
    14 inline int ad (int a,int b) { a=a+b; if(a>=mod) a-=mod; return a; }
    15 
    16 int solve ()
    17 {
    18     dp[0][0][0]=1;
    19     for (R i=0;i<n;++i)
    20     {
    21         no=i&1;
    22         nex=no^1;
    23         memset(dp[nex],0,sizeof(dp[nex]));
    24         for (R m1=0;m1<a;++m1)
    25             for (R m2=0;m2<b;++m2)
    26             {
    27                 if(!dp[no][m1][m2]) continue;
    28                 dp[nex][m1][(m2+a)%b]=ad(dp[no][m1][m2],dp[nex][m1][(m2+a)%b]);
    29                 dp[nex][(m1+b)%a][m2]=ad(dp[no][m1][m2],dp[nex][(m1+b)%a][m2]);
    30             }
    31     }
    32     int ans=0;
    33     for (R m1=0;m1<a;++m1)
    34         for (R m2=0;m2<b;++m2)
    35             if(m1==0||m2==0) ans=ad(ans,dp[n&1][m1][m2]);
    36     return ans;
    37 }
    38 
    39 int main()
    40 {
    41     scanf("%d%d%d",&n,&a,&b);
    42     printf("%d",solve());
    43     return 0;
    44 }
    T1

      T2:求逆序对数量*360。没了。 

      
     1 # include <cstdio>
     2 # include <iostream>
     3 # include <cstring>
     4 # include <string>
     5 # include <algorithm>
     6 # define R register int
     7 # define lowbit(i) (i&(-i))
     8 # define mod 1000000007
     9 
    10 using namespace std;
    11 
    12 const int maxn=500005;
    13 struct nod
    14 {
    15     int key,val;
    16 }a[maxn];
    17 int n,v[maxn];
    18 int t[maxn],ans,cnt;
    19 
    20 bool cmp (nod a,nod b) { return a.val<b.val; }
    21 
    22 void add (int pos,int val)
    23 {
    24     for (R i=pos;i<=cnt;i+=lowbit(i)) t[i]+=val;
    25 }
    26 
    27 int ask (int pos)
    28 {
    29     int ans=0;
    30     for (R i=pos;i;i-=lowbit(i)) ans+=t[i];
    31     return ans;     
    32 }
    33 
    34 int main()
    35 {
    36     scanf("%d",&n);
    37     for (R i=1;i<=n;++i)
    38         scanf("%d",&a[i].val),a[i].key=i;
    39     sort(a+1,a+1+n,cmp);
    40     a[0].val=a[1].val+1;
    41     for (R i=1;i<=n;++i)
    42     {
    43         if(a[i].val!=a[i-1].val) ++cnt;
    44         v[ a[i].key ]=cnt;
    45     }
    46     for (R i=1;i<=n;++i)
    47     {
    48         ans+=ask(cnt)-ask(v[i]);
    49         if(ans>=mod) ans-=mod;
    50         add(v[i],1);    
    51     }
    52     ans=(long long)ans*360%mod;
    53     printf("%d",ans);
    54     return 0;
    55 }
    T2

      T3:给定一棵正边权的树,求离每个点最远的点有多远;

      有一个定理:离每个点最远的点必然是直径端点上的一点,不过...我不是这么做的。

      以任意点为端点的最长路要么在它的子树里面,要么是从父亲走过来的,经典的$up and down$题目.注意,父亲的最长路有可能本来就是从自己这里走过去的,再用父亲来更新就会走重复的路径了.那怎么办呢?再记录一条次长路径即可,细节什么的...自己想吧。 

      
     1 # include <cstdio>
     2 # include <iostream>
     3 # include <cstring>
     4 # include <string>
     5 # define R register int
     6 
     7 using namespace std;
     8 
     9 const int maxn=1000006;
    10 int n,h,x,y,co,firs[maxn],dep[maxn],m1[maxn],m2[maxn];
    11 struct edge
    12 {
    13     int too,nex,co;
    14 }g[maxn<<1];
    15 
    16 int read()
    17 {
    18     int x=0,f=1;
    19     char c=getchar();
    20     while (!isdigit(c)) { if(c=='-') f=-f; c=getchar(); }
    21     while (isdigit(c)) { x=(x<<3)+(x<<1)+(c^48); c=getchar(); }
    22     return x*f;
    23 }
    24 
    25 void add (int x,int y,int co)
    26 {
    27     g[++h].too=y;
    28     g[h].co=co;
    29     g[h].nex=firs[x];
    30     firs[x]=h;
    31 }
    32 
    33 void upp (int x)
    34 {
    35     int j,len;
    36     for (R i=firs[x];i;i=g[i].nex)
    37     {
    38         j=g[i].too;
    39         if(dep[j]) continue;
    40         dep[j]=dep[x]+1;
    41         upp(j);
    42         len=m1[j]+g[i].co;
    43         if(len>m1[x]) m2[x]=m1[x],m1[x]=len;
    44         else if(len==m1[x]) m2[x]=len;
    45         else m2[x]=max(m2[x],len);
    46     }
    47 }
    48 
    49 void dowwn (int x)
    50 {
    51     int j,len;
    52     for (R i=firs[x];i;i=g[i].nex)
    53     {
    54         j=g[i].too;
    55         if(dep[j]<dep[x]) continue;
    56         len=m1[x];
    57         if(len==m1[j]+g[i].co) len=m2[x];
    58         len+=g[i].co;
    59         if(len>m1[j]) m1[j]=len;
    60         else if(len==m1[j]) m2[j]=len;
    61         else m2[j]=max(m2[j],len);
    62         dowwn(j);
    63     }
    64 }
    65 
    66 int main()
    67 {
    68     n=read();
    69     for (R i=1;i<n;++i)
    70     {
    71         x=read(),y=read(),co=read();
    72         add(x,y,co);
    73         add(y,x,co);
    74     }
    75     dep[1]=1;
    76     upp(1);
    77     dowwn(1);
    78     for (R i=1;i<n;++i)
    79         printf("%d ",m1[i]);
    80     printf("%d",m1[n]);
    81     return 0;
    82 }
    T3

      T4:带修改动态逆序对。

      $n$为序列长度,$m$为修改次数.

      

      这题好啊,不用写代码,只需要写一个做法的$txt$,学姐看做法给分qwq.正好是只会说不会写.

      

      这个做法竟然被给了满分QAQ

      ---shzr

  • 相关阅读:
    开关门(结构体)
    洗牌问题(找规律)
    七夕节(hd1215)干嘛今天做这题T_T
    三角形(hd1249)
    寒冰王座(hd1248)
    钱币兑换问题(hd1284)
    计算机模拟(hd1283)
    回文数猜想(hd1282)
    贪吃蛇代码
    变形课hd1181(DFS)
  • 原文地址:https://www.cnblogs.com/shzr/p/9740237.html
Copyright © 2020-2023  润新知