• 2017 多校联合训练 4 题解


    Problem 1004

    直接用数组模拟

    为了避免memset

    可以一遍正着统计,一遍倒着统计

    注意统计的时候不能出现乘除法

    不然会T

    然后记录一个cnt

    cnt大于2e8就跳出

    同时有效数字的位数够了也跳出

    当然所有的数都不同以及只有2个数相同要特殊处理

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<algorithm>
    #include<cstring>
    #include<string>
    #include<vector>
    #include<map>
    #include<set>
    #include<queue>
    using namespace std;
    const double eps=1e-5;
    int _,n,a[60010];
    int p[60010],q[60010];
    int main()
    {
        scanf("%d",&_);
        while (_--)
        {
            scanf("%d",&n);
            int i,j;
            for (i=1;i<=n;i++)
            {
                scanf("%d",&a[i]);
                p[a[i]]=0,q[a[i]]=0;
            }
            int mx=0,cnt=0;
            for (i=1;i<=n;i++)
            {
                if (q[a[i]])
                    mx=max(mx,i-q[a[i]]);
                else cnt++;
                q[a[i]]=i;
            }
            if (cnt==1)
            {
                printf("%.9f
    ",1.0/n);
                continue;
            }
            else if (cnt==2)
            {
                if (2*(mx-1)<n) printf("%.9f
    ",2.0/n);
                else printf("%.9f
    ",1.0/(mx-1));
                continue;
            }
            p[a[1]]++;
            int fz=1;
            double ans=cnt*1.0/n;
            cnt=0;
            for (i=2;i<=n;i++)
            {
                int nfz;
                if (i&1)
                {
                    if (!p[a[n-i+1]])
                        fz++;
                    p[a[n-i+1]]++;
                    int pre=n;
                    nfz=fz;
                    for (j=n-i;j>=1;j--)
                    {
                        p[a[pre]]--;
                        if (!p[a[pre]]) fz--;
                        if (!p[a[j]]) fz++;
                        p[a[j]]++;
                        if (fz<nfz) nfz=fz;
                        pre--;
                        cnt++;
                        if (cnt>2e8) break;
                    }
                }
                else
                {
                    if (!p[a[i]]) fz++;
                    p[a[i]]++;
                    int pre=1;
                    nfz=fz;
                    for (j=i+1;j<=n;j++)
                    {
                        p[a[pre]]--;
                        if (!p[a[pre]]) fz--;
                        if (!p[a[j]]) fz++;
                        p[a[j]]++;
                        if (fz<nfz) nfz=fz;
                        pre++;
                        cnt++;
                        if (cnt>2e8) break;
                    }
                }
                double as=nfz*1.0/i;
                //cout<<nfz<<" "<<i<<endl;
                if (as<ans) ans=as;
                if (ans<eps) break;
                if (cnt>2e8) break;
            }
            printf("%.9f
    ",ans);
        }
        return 0;
    }
    View Code

    Problem 1005

    w=min(d1,2,d2,3)w=min(d1,2​​,d2,3​​)

    因为一条边可以往返跑2ci

    所以如果存在距离为d的方案

    那么一定存在距离为d+2w的方案

    设f[i][j]为从起点出发到i,距离模2w为j时的最短路

    根据f[2][j]解不等式即可

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<cstdlib>
     5 #include<algorithm>
     6 #include<cstring>
     7 #include<string>
     8 #include<vector>
     9 #include<map>
    10 #include<set>
    11 #include<queue>
    12 #include<functional>
    13 using namespace std;
    14 typedef long long ll;
    15 typedef pair<ll,int> P;
    16 const ll inf=1ll<<62;
    17 int _,g[4],st;
    18 ll f[4][60001],k;
    19 priority_queue<P,vector<P>,greater<P> >q;
    20 void upd(int x,int y,ll z)
    21 {
    22     if (z<f[x][y])
    23     {
    24         f[x][y]=z;
    25         q.push({z,y<<2|x});
    26     }
    27 }
    28 int main()
    29 {
    30     scanf("%d",&_);
    31     while (_--)
    32     {
    33         scanf("%lld%d%d%d%d",&k,&g[0],&g[1],&g[2],&g[3]);
    34         st=min(g[0],g[1])*2;
    35         int i,j;
    36         for (i=0;i<4;i++)
    37             for (j=0;j<st;j++) f[i][j]=inf;
    38         upd(1,0,0);
    39         while (!q.empty())
    40         {
    41             P t=q.top();
    42             q.pop();
    43             int x=t.second%4;
    44             int y=t.second/4;
    45             if (f[x][y]<t.first) continue;
    46             upd((x+1)%4,(y+g[x])%st,t.first+g[x]);
    47             upd((x+3)%4,(y+g[(x+3)%4])%st,t.first+g[(x+3)%4]);
    48         }
    49         ll ans=inf;
    50         for (i=0;i<st;i++)
    51             if (f[1][i]<k)
    52             {
    53                 ll sum=f[1][i]+(k-f[1][i])/st*st;
    54                 while (sum<k) sum+=st;
    55                 ans=min(ans,sum);
    56             }
    57             else
    58                 ans=min(ans,f[1][i]);
    59         printf("%lld
    ",ans);
    60     }
    61     return 0;
    62 }
    View Code

    Problem 1007

    度数为1的点匹配方案是唯一的

    先拓扑排序去掉所有度数为1的点

    剩下的图的每个连痛快是个环

    间隔取环上的点

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cmath>
      4 #include<cstdlib>
      5 #include<algorithm>
      6 #include<cstring>
      7 #include<string>
      8 #include<vector>
      9 #include<map>
     10 #include<set>
     11 #include<queue>
     12 using namespace std;
     13 typedef long long ll;
     14 const ll mod=998244353;
     15 int _,n,du[600010],p[600100];
     16 bool vis[600010];
     17 vector<pair<int,int>> a[600010];
     18 int get(int x,int y)
     19 {
     20     for (auto u:a[x])
     21         if (u.first==y) return u.second;
     22 }
     23 int main()
     24 {
     25     scanf("%d",&_);
     26     while (_--)
     27     {
     28         scanf("%d",&n);
     29         int i,j;
     30         for (i=1;i<=2*n;i++)
     31             a[i].clear();
     32         memset(du,0,sizeof(du));
     33         memset(vis,false,sizeof(vis));
     34         for (i=1;i<=n;i++)
     35             for (j=0;j<2;j++)
     36             {
     37                 int x,y;
     38                 scanf("%d%d",&x,&y);
     39                 a[i].push_back({x+n,y});
     40                 a[x+n].push_back({i,y});
     41                 du[i]++;
     42                 du[x+n]++;
     43             }
     44         n<<=1;
     45         queue<int> q;
     46         for (i=1;i<=n;i++)
     47             if (du[i]==1)
     48                 q.push(i);
     49         ll ans=1;
     50         while (!q.empty())
     51         {
     52             int x=q.front();
     53             q.pop();
     54             int y;
     55             for (auto u:a[x])
     56                 if (!vis[u.first])
     57                 {
     58                     y=u.first;    
     59                     ans=1ll*ans*u.second%mod;
     60                     break;
     61                 }
     62             vis[x]=vis[y]=true;
     63             for (auto u:a[y])
     64                 if (!vis[u.first])
     65                 {
     66                     du[u.first]--;
     67                     if (du[u.first]==1)
     68                         q.push(u.first);
     69                 }
     70         }
     71         for (i=1;i<=n;i++)
     72             if (!vis[i])
     73             {
     74                 vis[i]=true;
     75                 int cnt=1;
     76                 p[cnt]=i;
     77                 int cm=i;
     78                 while (true)
     79                 {
     80                     bool fg=true;
     81                     for (auto u:a[cm])
     82                         if (!vis[u.first])
     83                         {
     84                             fg=false;
     85                             cm=u.first;
     86                             break;
     87                         }
     88                     if (fg) break;
     89                     //cout<<cm<<" ";
     90                     vis[cm]=true;
     91                     p[++cnt]=cm;
     92                 }
     93                 //cout<<endl;
     94                 p[cnt+1]=p[1];
     95                 ll x=1,y=1;
     96                 for (j=1;j<=cnt;j+=2) x=1ll*x*get(p[j],p[j+1])%mod;
     97                 for (j=2;j<=cnt;j+=2) y=1ll*y*get(p[j],p[j+1])%mod;
     98                 ans=1ll*ans*(x+y)%mod;    
     99             }
    100         printf("%lld
    ",ans);
    101     }
    102     return 0;
    103 }
    View Code

    Problem 1011

    按照题意模拟即可

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cmath>
      4 #include<cstdlib>
      5 #include<algorithm>
      6 #include<cstring>
      7 #include<string>
      8 #include<vector>
      9 #include<map>
     10 #include<set>
     11 #include<queue>
     12 using namespace std;
     13 const char s[10][8][5]=
     14 {{".XX.",
     15   "X..X",
     16   "X..X",
     17   "....",
     18   "X..X",
     19   "X..X",
     20   ".XX."},
     21  
     22  {"....",
     23   "...X",
     24   "...X",
     25   "....",
     26   "...X",
     27   "...X",
     28   "...."},
     29  
     30  {".XX.",
     31   "...X",
     32   "...X",
     33   ".XX.",
     34   "X...",
     35   "X...",
     36   ".XX.",},
     37  
     38  {".XX.",
     39   "...X",
     40   "...X",
     41   ".XX.",
     42   "...X",
     43   "...X",
     44   ".XX." },
     45  
     46  {"....",
     47   "X..X",
     48   "X..X",
     49   ".XX.",
     50   "...X",
     51   "...X",
     52   "...."},
     53  
     54  {".XX.",
     55   "X...",
     56   "X...",
     57   ".XX.",
     58   "...X",
     59   "...X",
     60   ".XX.",},
     61   
     62  {".XX.",
     63   "X...",
     64   "X...",
     65   ".XX.",
     66   "X..X",
     67   "X..X",
     68   ".XX.",},
     69  
     70  {".XX.",
     71   "...X",
     72   "...X",
     73   "....",
     74   "...X",
     75   "...X",
     76   "...."},
     77   
     78  { ".XX.",
     79    "X..X",
     80    "X..X",
     81    ".XX.",
     82    "X..X",
     83    "X..X",
     84    ".XX.",},
     85  
     86  { ".XX.",
     87    "X..X",
     88    "X..X",
     89    ".XX.",
     90    "...X",
     91    "...X",
     92    ".XX.",}
     93   };
     94 char c[8][22];
     95 void check(int pos)
     96 {
     97     int num,i,j;
     98     for (num=0;num<10;num++)
     99     {
    100         bool ok=true;
    101         for (i=0;i<7;i++)
    102         {
    103             for (j=pos;j<=pos+3;j++)
    104                 if (c[i][j]!=s[num][i][j-pos])
    105                 {
    106                     ok=false;
    107                     break;
    108                 }
    109             if (!ok) break;
    110         }
    111         if (ok)
    112         {
    113             printf("%d",num);
    114             return;
    115         }
    116     }
    117 }
    118 int main()
    119 {
    120     int _;
    121     scanf("%d",&_);
    122     while (_--)
    123     {
    124         int i,j;
    125         for (i=0;i<7;i++)
    126             scanf("%s",c[i]);
    127         check(0);
    128         check(5);
    129         printf(":");
    130         check(12);
    131         check(17);
    132         printf("
    ");
    133     }
    134     return 0;
    135 }
    View Code

    Problem 1012

    f[i][j][k]表示只考虑a,b两个数组,上升下降状态是k的方案数

    直接暴力枚举会T

    这时可以建立辅助数组g和h

    g[i][y][z]表示从f[x][y][z]开始,要更新的是i的方案数

    h[i][j][z]表示从f[x][y][z]开始,已经经过g,要更新的是j的方案数

    这样每次就只有一个变量在动

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<cstdlib>
     5 #include<algorithm>
     6 #include<cstring>
     7 #include<string>
     8 #include<vector>
     9 #include<map>
    10 #include<set>
    11 #include<queue>
    12 using namespace std;
    13 const int mod=998244353;
    14 int _,n,m,a[2010],b[2010];
    15 int g[2010][2010][2],h[2010][2010][2];
    16 int main()
    17 {
    18     scanf("%d",&_);
    19     while (_--)
    20     {
    21         scanf("%d%d",&n,&m);
    22         int i,j,k;
    23         for (i=1;i<=n;i++) scanf("%d",&a[i]);
    24         for (i=1;i<=m;i++) scanf("%d",&b[i]);
    25         memset(g,0,sizeof(g));
    26         memset(h,0,sizeof(h));
    27         int ans=0;
    28         for (i=1;i<=n;i++)
    29             for (j=1;j<=m;j++)
    30                 for (k=0;k<2;k++)
    31                 {
    32                     if (a[i]==b[j])
    33                     {
    34                         int t=h[i][j][1-k];
    35                         if (!k) t=(t+1)%mod;
    36                         if (t)
    37                         {
    38                             ans=(ans+t)%mod;
    39                             g[i+1][j][k]=(g[i+1][j][k]+t)%mod;
    40                         }
    41                     }
    42                     if (g[i][j][k])
    43                     {
    44                         g[i+1][j][k]=(g[i+1][j][k]+g[i][j][k])%mod;
    45                         if (!k)
    46                         {
    47                             if (a[i]>b[j])
    48                                 h[i][j+1][k]=(h[i][j+1][k]+g[i][j][k])%mod;
    49                         }
    50                         else
    51                         {
    52                             if (a[i]<b[j])
    53                                 h[i][j+1][k]=(h[i][j+1][k]+g[i][j][k])%mod;
    54 
    55                         }
    56                     }
    57                     if (h[i][j][k]) h[i][j+1][k]=(h[i][j+1][k]+h[i][j][k])%mod;
    58                 }
    59         printf("%d
    ",ans);
    60     }
    61     return 0;
    62 }
    View Code
  • 相关阅读:
    委托与事件
    JSON
    JavascriptBoolean运算符
    SQL执行字符串
    ref和out与SQL中的output
    早绑定、晚绑定
    浅复制和深复制
    Android Fragments 详细使用
    Android 两种为自定义组件添加属性的使用方法和区别
    Gallery 3D+倒影 滑动切换图片示例(转)
  • 原文地址:https://www.cnblogs.com/cxhscst2/p/7441885.html
Copyright © 2020-2023  润新知