• 2018 ACM-ICPC南京区域赛题解


    解题过程

    开场开A,A题shl看错题意,被制止。然后开始手推A,此时byf看错E题题意,开始上机。推出A的规律后,shl看了E题,发现题意读错。写完A题,忘记判断N=0的情况,WA+1。过了A后,shl重新写E,lfw开始开J题,E题过不了样例,lfw多次起立让shl调试,然后shl拿到E的一血,lfw之后过了J。byf开始开I题,shl口胡出M做法,然后lfw和shl一起推G题。byf过了I题后,shl推出G题,byf去写。然后lfw开始计算几何,经过查错后过掉,然后shl开始开M题,过掉后还剩最后半小时,无题可做。

    最后罚时很多,因为前期签到题过得太慢,A题40+分钟才过,J题1小时40分钟才过。

    题解

    A - Adrien and Austin

     题解:给你n给石头,下标依次为1~n,然后两个人轮流取石头,每次取1~k个连续下标的石头,最后不能取得输掉比赛。问你谁会获胜。

    找规律,首先,n==0时,第一个人必败。k==1时,n为奇数时先手必胜。k>1时,先手必胜.

    参考代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long LL;
     4 const int mod=1e9+7;
     5 LL quick_pow(LL a,LL b)
     6 {
     7     LL ans=1;
     8     while(b)
     9     {
    10         if(b&1) ans=ans*a%mod;
    11         a=a*a%mod;
    12         b>>=1;
    13     }
    14     return ans;
    15 }
    16 int main()
    17 {
    18     int t;
    19     scanf("%d",&t);
    20     int l24=quick_pow(24,mod-2);
    21     while(t--)
    22     {
    23         int n;
    24         scanf("%d",&n);
    25         LL ans=1;
    26         ans=ans*n%mod;
    27         ans=ans*(n+1)%mod;
    28         ans=ans*(n+2)%mod;
    29         ans=ans*(n+3)%mod;
    30         ans=ans*l24%mod;
    31         printf("%lld
    ",ans);
    32     }
    33 }
    View Code

    B - Tournament

     Unsolved.

    C - Cherry and Chocolate

     Unsolved.

    D - Country Meow

     队友写的.题解:https://blog.csdn.net/liufengwei1/article/details/89303612

    参考代码:

      1 #include<bits/stdc++.h>
      2 #define maxl 110
      3 #define eps 1e-8
      4 struct point
      5 {
      6   double x,y,z;
      7   point(double a=0,double b=0,double c=0)
      8   {
      9     x=a;y=b;z=c;
     10   }
     11 };
     12 
     13 int npoint,nouter;
     14 point pt[maxl],outer[4],res;
     15 double radius,tmp,ans;
     16 
     17 inline double dist(point p1,point p2)
     18 {
     19   double dx=p1.x-p2.x,dy=p1.y-p2.y,dz=p1.z-p2.z;
     20   return (dx*dx+dy*dy+dz*dz);
     21 }
     22 
     23 inline double dot(point p1,point p2)
     24 {
     25   return p1.x*p2.x+p1.y*p2.y+p1.z*p2.z;
     26 }
     27 
     28 inline void ball()
     29 {
     30   point q[3];double m[3][3],sol[3],L[3],det;
     31   int i,j;
     32   res.x=res.y=res.z=radius=0;
     33   switch(nouter)
     34     {
     35     case 1: res=outer[0];break;
     36     case 2:
     37       res.x=(outer[0].x+outer[1].x)/2;
     38       res.y=(outer[0].y+outer[1].y)/2;
     39       res.z=(outer[0].z+outer[1].z)/2;
     40       radius=dist(res,outer[0]);
     41       break;
     42     case 3:
     43       for(int i=0;i<2;i++)
     44     {
     45       q[i].x=outer[i+1].x-outer[0].x;
     46       q[i].y=outer[i+1].y-outer[0].y;
     47       q[i].z=outer[i+1].z-outer[0].z;
     48     }
     49       for(int i=0;i<2;i++)
     50     for(int j=0;j<2;j++)
     51       m[i][j]=dot(q[i],q[j])*2;
     52       for(int i=0;i<2;i++)
     53     sol[i]=dot(q[i],q[i]);
     54       if(fabs(det=m[0][0]*m[1][1]-m[0][1]*m[1][0])<eps)
     55     return;
     56       L[0]=(sol[0]*m[1][1]-sol[1]*m[0][1])/det;
     57       L[1]=(sol[1]*m[0][0]-sol[0]*m[1][0])/det;
     58       res.x=outer[0].x+q[0].x*L[0]+q[1].x*L[1];
     59       res.y=outer[0].y+q[0].y*L[0]+q[1].y*L[1];
     60       res.z=outer[0].z+q[0].z*L[0]+q[1].z*L[1];
     61       radius=dist(res,outer[0]);
     62       break;
     63     case 4:
     64       for(int i=0;i<3;i++)
     65     {
     66       q[i].x=outer[i+1].x-outer[0].x;
     67       q[i].y=outer[i+1].y-outer[0].y;
     68       q[i].z=outer[i+1].z-outer[0].z;
     69       sol[i]=dot(q[i],q[i]);
     70     }
     71       for(int i=0;i<3;i++)
     72     for(int j=0;j<3;j++)
     73       m[i][j]=dot(q[i],q[j])*2;
     74       det=m[0][0]*m[1][1]*m[2][2]
     75     + m[0][1]*m[1][2]*m[2][0]
     76     + m[0][2]*m[2][1]*m[1][0]
     77     - m[0][2]*m[1][1]*m[2][0]
     78     - m[0][1]*m[1][0]*m[2][2]
     79     - m[0][0]*m[1][2]*m[2][1];
     80       if(fabs(det)<eps) return;
     81       for(int j=0;j<3;j++)
     82     {
     83       for(int i=0;i<3;i++)
     84         m[i][j]=sol[i];
     85       L[j]=(m[0][0]*m[1][1]*m[2][2]
     86         +m[0][1]*m[1][2]*m[2][0]
     87         +m[0][2]*m[2][1]*m[1][0]
     88         -m[0][2]*m[1][1]*m[2][0]
     89         -m[0][1]*m[1][0]*m[2][2]
     90         -m[0][0]*m[1][2]*m[2][1])/det;
     91       for(int i=0;i<3;i++)
     92         m[i][j]=dot(q[i],q[j])*2;
     93     }
     94       res=outer[0];
     95       for(int i=0;i<3;i++)
     96     {
     97       res.x+=q[i].x*L[i];
     98       res.y+=q[i].y*L[i];
     99       res.z+=q[i].z*L[i];
    100     }
    101       radius=dist(res,outer[0]);
    102     }
    103 }
    104 
    105 inline void minball(int n)
    106 {
    107   ball();
    108   if(nouter<4)
    109     for(int i=0;i<n;i++)
    110       if(dist(res,pt[i])-radius>eps)
    111     {
    112       outer[nouter]=pt[i];
    113       ++nouter;
    114       minball(i);
    115       --nouter;
    116       if(i>0)
    117         {
    118           point Tt=pt[i];
    119           memmove(&pt[1],&pt[0],sizeof(point)*i);
    120           pt[0]=Tt;
    121         }
    122     }
    123 }
    124 
    125 inline double smallest_ball()
    126 {
    127   radius=-1;
    128   for(int i=0;i<npoint;i++)
    129     if(dist(res,pt[i])-radius>eps)
    130       {
    131     nouter=1;
    132     outer[0]=pt[i];
    133     minball(i);
    134       }
    135   return sqrt(radius);
    136 }
    137 
    138 inline void prework()
    139 {
    140   for(int i=0;i<npoint;i++)
    141     scanf("%lf%lf%lf",&pt[i].x,&pt[i].y,&pt[i].z);
    142 }
    143 
    144 inline void mainwork()
    145 {
    146   ans=smallest_ball();
    147 }
    148 
    149 inline void print()
    150 {
    151   printf("%.5f
    ",ans);
    152 }
    153 
    154 int main()
    155 {
    156   while(~scanf("%d",&npoint))
    157     {
    158       prework();
    159       mainwork();
    160       print();
    161     }
    162   return 0;
    163 }
    View Code

    E - Eva and Euro coins

     题解:给你两个01串,然后连续k个0可以翻转为1,连续k个1可以翻转为0.问你这两个01串是否可以变成相同的串。

    可以利用归约。连续k个0或1可以归约掉。最后判断是否相同即可。

    参考代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn=1e6+5;
     4 char s[maxn],t[maxn];
     5 int cnt[maxn][2];
     6 int n,k,tmp;
     7 void work(char st[])
     8 {
     9     memset(cnt,0,sizeof(cnt));
    10     cnt[0][0]=-1;tmp=0;
    11     for(int i=1;i<=n;++i)
    12     {
    13         cnt[++tmp][0]=st[i]-'0';
    14         cnt[tmp][1] = cnt[tmp-1][0]==st[i]-'0'?cnt[tmp-1][1]+1:1;
    15         if(cnt[tmp][1]==k) tmp-=k;
    16     }
    17     for(int i=1;i<=n;++i) {if(i<=tmp) st[i]=cnt[i][0]+'0';else st[i]='0';}
    18 }
    19 int main()
    20 {
    21     scanf("%d%d",&n,&k);
    22     scanf("%s",s+1);
    23     scanf("%s",t+1);
    24     work(s);work(t);
    25     for(int i=1;i<=n;++i) {if(s[i]!=t[i]) {puts("No");return 0;}}
    26     puts("Yes"); 
    27     return 0;
    28 }
    View Code

    F - Frank

     Unsolved.

    G - Pyramid

     题解:打表找规律,ans=n(n+1)(n+2)(n+3).

    参考代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long LL;
     4 const int mod=1e9+7;
     5 LL quick_pow(LL a,LL b)
     6 {
     7     LL ans=1;
     8     while(b)
     9     {
    10         if(b&1) ans=ans*a%mod;
    11         a=a*a%mod;
    12         b>>=1;
    13     }
    14     return ans;
    15 }
    16 int main()
    17 {
    18     int t;
    19     scanf("%d",&t);
    20     int l24=quick_pow(24,mod-2);
    21     while(t--)
    22     {
    23         int n;
    24         scanf("%d",&n);
    25         LL ans=1;
    26         ans=ans*n%mod;
    27         ans=ans*(n+1)%mod;
    28         ans=ans*(n+2)%mod;
    29         ans=ans*(n+3)%mod;
    30         ans=ans*l24%mod;
    31         printf("%lld
    ",ans);
    32     }
    33 }
    View Code

    H - Huge Discount

     Unsolved.

    I - Magic Potion

     队友写的,好像是最大流,题解待更。

    参考代码:

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 const int maxn=1010;
      4 const int maxm=1e5+5;
      5 const int inf=0x3f3f3f3f;
      6 struct Edge{
      7     int to,nxt,cap,flow;
      8 }edge[maxm];
      9 int tol;
     10 int head[maxn];
     11 void init(){
     12     tol=2;
     13     memset(head,-1,sizeof(head));
     14 }
     15 void AddEdge(int u,int v,int w,int rw=0){
     16     edge[tol].to=v;edge[tol].cap=w;edge[tol].flow=0;
     17     edge[tol].nxt=head[u];head[u]=tol++;
     18     edge[tol].to=u;edge[tol].cap=rw;edge[tol].flow=0;
     19     edge[tol].nxt=head[v];head[v]=tol++;
     20 }
     21 int Q[maxn];
     22 int dep[maxn],cur[maxn],sta[maxn];
     23 bool bfs(int s,int t,int n){
     24     int front=0,tail=0;
     25     memset(dep,-1,sizeof(dep[0])*(n+1));
     26     dep[s]=0;
     27     Q[tail++]=s;
     28     while(front<tail){
     29         int u=Q[front++];
     30         for(int i=head[u];i!=-1;i=edge[i].nxt){
     31             int v=edge[i].to;
     32             if(edge[i].cap>edge[i].flow&&dep[v]==-1){
     33                 dep[v]=dep[u]+1;
     34                 if(v==t) return true;
     35                 Q[tail++]=v;
     36             }
     37         }
     38     }
     39     return false;
     40 }
     41 int dinic(int s,int t,int n){
     42     int maxflow=0;
     43     while(bfs(s,t,n)){
     44         for(int i=0;i<n;i++) cur[i]=head[i];
     45         int u=s,tail=0;
     46         while(cur[s]!=-1){
     47             if(u==t){
     48                 int tp=inf;
     49                 for(int i=tail-1;i>=0;i--)
     50                 {
     51                     tp=min(tp,edge[sta[i]].cap-edge[sta[i]].flow);
     52                 }
     53                 maxflow+=tp;
     54                 for(int i=tail-1;i>=0;i--){
     55                     edge[sta[i]].flow+=tp;
     56                     edge[sta[i]^1].flow-=tp;
     57                     if(edge[sta[i]].cap-edge[sta[i]].flow==0) tail=i;
     58                 }
     59                 u=edge[sta[tail]^1].to;
     60             }
     61             else if(cur[u]!=-1&&edge[cur[u]].cap>edge[cur[u]].flow&&dep[u]+1==dep[edge[cur[u]].to]){
     62                 sta[tail++]=cur[u];
     63                 u=edge[cur[u]].to;
     64             }
     65             else{
     66                 while(u!=s&&cur[u]==-1) u=edge[sta[--tail]^1].to;
     67                 cur[u] = edge [cur[u]].nxt;
     68             }
     69         }
     70     }
     71     return maxflow;
     72 }
     73 int main()
     74 {
     75     init();
     76     int n,m,k;
     77     scanf("%d%d%d",&n,&m,&k);
     78     int ti,mi;
     79     int ss=0,t=n+m+5;
     80     int s1=1,s2=2;
     81     for(int i=1;i<=n;i++) AddEdge(s1,i+2,1);
     82     for(int i=1;i<=n;i++) AddEdge(s2,i+2,1);
     83     AddEdge(ss,s1,n);
     84     AddEdge(ss,s2,k);
     85     for(int i=1;i<=n;i++)
     86     {
     87         scanf("%d",&ti);
     88         for(int j=1;j<=ti;j++)
     89         {
     90             scanf("%d",&mi);
     91             AddEdge(i+2,n+2+mi,1);
     92         }
     93     }
     94     for(int i=1;i<=m;i++)
     95     {
     96         AddEdge(i+n+2,t,1);
     97     }
     98     int ans=dinic(ss,t,t+1);
     99     printf("%d
    ",ans);
    100 }    
    101     
    View Code

    J - Prime Game

     队友写的,题解:https://blog.csdn.net/liufengwei1/article/details/89303678

    参考代码:

     1 #include<bits/stdc++.h>
     2 #define maxl 1000010
     3 using namespace std;
     4 
     5 int n;
     6 int a[maxl],p[maxl],dy[maxl];
     7 long long v[maxl];
     8 bool no[maxl];
     9 vector <int> f[maxl];
    10 long long ans;
    11 
    12 inline void shai()
    13 {
    14   no[1]=true;
    15   int t,j;
    16   for(int i=2;i<maxl;i++)
    17     {
    18       if(!no[i]) p[++p[0]]=i,dy[i]=i;
    19       j=1,t=i*p[1];
    20       while(j<=p[0] && t<maxl)
    21     {
    22       dy[t]=p[j];
    23       no[t]=true;
    24       if(i%p[j]==0)
    25         break;
    26       t=i*p[++j];
    27     }
    28     }
    29 }
    30 
    31 inline void prework()
    32 {
    33   for(int i=1;i<=p[0];i++)
    34     f[p[i]].clear();
    35   for(int i=1;i<=n;i++)
    36     {
    37       scanf("%d",&a[i]);
    38       int x=a[i],last=0;
    39       while(x>1)
    40     {
    41       if(dy[x]!=last)
    42         f[dy[x]].push_back(i);
    43       last=dy[x];
    44       x/=dy[x];
    45     }
    46     }
    47 }
    48 
    49 inline void mainwork()
    50 {
    51   ans=0;int l,r,len;
    52   long long tmp;
    53   for(int i=1;i<=p[0];i++)
    54     if(f[p[i]].size()>0)
    55       {
    56     tmp=v[n];
    57     l=1;r=0;len=f[p[i]].size();
    58     if(f[p[i]][0]>1)
    59       tmp-=v[f[p[i]][0]-1];
    60     for(int j=0;j<len-1;j++)
    61       if(f[p[i]][j+1]>f[p[i]][j]+1)
    62       {
    63         l=f[p[i]][j]+1;r=f[p[i]][j+1]-1;
    64         tmp-=v[r-l+1];
    65       }
    66     if(f[p[i]][len-1]<n)
    67       tmp-=v[n-f[p[i]][len-1]];
    68     ans+=tmp;
    69       }
    70 }
    71 
    72 inline void print()
    73 {
    74   printf("%lld
    ",ans);
    75 }
    76 
    77 int main()
    78 {
    79   shai();
    80   for(long long i=1;i<maxl;i++)
    81     v[i]=i*(i+1)/2;
    82   while(~scanf("%d",&n))
    83     {
    84       prework();
    85       mainwork();
    86       print();
    87     }
    88   return 0;
    89 }
    View Code

    K - Kangaroo Puzzle

     随机化。。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 char s[25][25];
     4 int n,m;
     5 int main()
     6 {
     7     scanf("%d%d",&n,&m);
     8     for(int i=1;i<=n;++i) scanf("%s",s[i]);
     9     srand(time(0));
    10     char str[4]={'L','R','U','D'};
    11     for(int i=1;i<=20;++i)printf("U");
    12     for(int i=1;i<=20;++i)printf("R");
    13     for(int i=1;i<=20;++i)printf("D");///////adsfag
    14     for(int i=1;i<=20;++i)printf("L");
    15     for(int i=1;i<=49920;++i)
    16     {
    17         int x=rand()%4;
    18         printf("%c",str[x]);
    19     }
    20     puts("");
    21     return 0;
    22 }
    View Code

    L - Lagrange the Chef

     Unsolved.

    M - Mediocre String Problem

     题解:给你两个字符串。让你从s1中取l,r一个子串,s2的前缀,把s2的前缀放到s1的后面,组成一个回文串,问你you多少种组合方式。

    我们可以把它转化为选l,x,r    和f使得l~x和1~f对称,把s1翻转,用exkmp处理,x~r为回文串.然后我们可以枚举r,用Manacher处理s1,把exnext反转,然后记录前缀和.

    即可。

    参考代码:

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 typedef long long ll;
      4 #define pii pair<int,int>
      5 const int INF=0x3f3f3f3f;
      6 const int maxn=1e6+10;
      7 char s[maxn],t[maxn];
      8 int lens,lent;
      9 int mynext[maxn],extend[maxn];
     10 ll sum[maxn];
     11 
     12 void pre_exkmp(char x[],int m,int nxt[])
     13 {
     14     nxt[0]=m;
     15     int j=0;
     16     while(j+1<m && x[j]==x[j+1]) j++;
     17     nxt[1]=j;
     18     int k=1;
     19     for(int i=2;i<m;++i)
     20     {
     21         int p=nxt[k]+k-1;
     22         int L=nxt[i-k];
     23         if(i+L<p+1) nxt[i]=L;
     24         else
     25         {    
     26             j=max(0,p-i+1);
     27             while(i+j<m&&x[i+j]==x[j]) j++;
     28             nxt[i]=j;
     29             k=i;
     30         }
     31     }
     32 }
     33 void exkmp(char x[],int m,char y[],int n,int nxt[],int extend[])
     34 {
     35     pre_exkmp(x,m,nxt);
     36     int j=0;
     37     while(j<n && j<m&& x[j]==y[j]) ++j;
     38     extend[0]=j;
     39     int k=0;
     40     for(int i=1;i<n;++i)
     41     {
     42         int p=extend[k]+k-1;
     43         int L=nxt[i-k];
     44         if(i+L<p+1) extend[i]=L;
     45         else
     46         {
     47             j=max(0,p-i+1);
     48             while(i+j<n&&j<m&&y[i+j]==x[j]) ++j;
     49             extend[i]=j;
     50             k=i;
     51         }
     52     }
     53 }
     54 char Ma[maxn<<2];
     55 int len[maxn<<1];
     56 void Manacher(char s[],int le)
     57 {    
     58     int l=0;
     59     Ma[l++]='$'; Ma[l++]='#';
     60     for(int i=0;i<le;++i) Ma[l++]=s[i],Ma[l++]='#';
     61     Ma[l]=0;
     62     int mx=0,id=0;
     63     for(int i=0;i<l;++i)
     64     {    
     65         len[i]=mx>i?min(len[2*id-i],mx-i):1;
     66         while(Ma[i+len[i]]==Ma[i-len[i]]) len[i]++;
     67         if(i+len[i]>mx) mx=i+len[i],id=i;
     68     }
     69 }
     70 //moban
     71 
     72 ll getsum(int l,int r)
     73 {    
     74     if(l>r) return 0;
     75     else if(l<=0) return sum[r];
     76     else return sum[r]-sum[l-1];
     77 }
     78 
     79 int main()
     80 {
     81     scanf("%s%s",s,t);
     82     lens=strlen(s);lent=strlen(t);
     83     Manacher(s,lens);//len[]
     84     reverse(s,s+lens);
     85     exkmp(t,lent,s,lens,mynext,extend);
     86     reverse(extend,extend+lens);
     87     sum[0]=extend[0];
     88     for(int i=1;i<lens;++i) sum[i]=sum[i-1]+extend[i];
     89     ll ans=0;
     90     for(int i=2;i<2*lens+3;++i)
     91     {    
     92         int cnt=len[i]-1;
     93         if(cnt==0 || len[i]==0) continue;
     94         if(cnt&1)
     95         {    
     96             int w=(i-2)/2;
     97             int r=w-1;
     98             int l=w-len[i]/2;
     99             ans+=getsum(l,r);
    100         }
    101         else
    102         {
    103             int w=(i-2-1)/2;
    104             int r=w-1;
    105             int l=w-cnt/2;
    106             ans+=getsum(l,r);
    107         }
    108     }
    109     printf("%lld
    ",ans);
    110 
    111     return 0;
    112 }
    View Code
  • 相关阅读:
    JVM 综述
    看 Netty 在 Dubbo 中如何应用
    Netty 心跳服务之 IdleStateHandler 源码分析
    Netty 高性能之道
    Netty 解码器抽象父类 ByteToMessageDecoder 源码解析
    Netty 源码剖析之 unSafe.write 方法
    Netty 出站缓冲区 ChannelOutboundBuffer 源码解析(isWritable 属性的重要性)
    Netty 源码剖析之 unSafe.read 方法
    Netty 内存回收之 noCleaner 策略
    Netty 源码阅读的思考------耗时业务到底该如何处理
  • 原文地址:https://www.cnblogs.com/csushl/p/10704713.html
Copyright © 2020-2023  润新知