zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    codeforce 266c Below the Diagonal 矩阵变换 (思维题)
    8月21日训练日记
    CodeForces 651B Beautiful Paintings
    CodeForces 651 C Watchmen
    CodeForces 17D Notepad(同余定理)
    CodeForces 19B Checkout Assistant
    Code Forces 18D Seller Bob(简单DP)
    HOJ Recoup Traveling Expenses(最长递减子序列变形)
    ZOJ 3469Food Delivery(区间DP)
    Code Forces 149DColoring Brackets(区间DP)
  • 原文地址:https://www.cnblogs.com/csushl/p/10704713.html
Copyright © 2011-2022 走看看