zoukankan      html  css  js  c++  java
  • 2016-2017 ACM-ICPC, Egyptian Collegiate Programming Contest(solved 8/11)

    这套题似乎是省选前做的,一直没来写题解~~~补上补上>_<

    链接:http://codeforces.com/gym/101147

    一样先放上惨不忍睹的成绩好了~~~

    Problem A 1Y(2h52min)

    Problem B DNF

    Problem C DNF

    Problem D 1Y(3min)

    Problem E 2Y(19min)

    Problem F DNF

    Problem G 6Y(2h40min)

    Problem H 1Y(36min)

    Problem I 2Y(4h55min)

    Problem J DNF

    Problem K DNF

    总之我非常非常菜就对了啦~

    Problem A:

    一个很棒棒的博弈题呢~

    博弈题不会的时候,不如打个表找找规律~~~

    然后分类讨论一下,

    a是奇数的时候,b的奇偶性决定了sg函数的值,

    a是偶数的时候,b%(a+1)决定了sg函数的值,(这里还要分类讨论一下)

    于是全部xor一下就做完了。

    代码如下:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 int read()
     4 {
     5     int x=0,f=1;char ch=getchar();
     6     while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
     7     while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
     8     return x*f;
     9 }
    10 int T,ans,n,a,b;
    11 int main()
    12 {
    13     freopen("powers.in","r",stdin);
    14     T=read();
    15     while (T--)
    16     {
    17         ans=0;
    18         n=read();
    19         for (int i=1;i<=n;i++)
    20         {
    21             a=read(),b=read();
    22             if (a%2==1)
    23             {
    24                 if (b%2==1) ans^=1;
    25             }
    26             else
    27             {
    28                 b=b%(a+1);
    29                 if (b==a) ans^=2;
    30                 if (b%2==1) ans^=1;
    31             }
    32         }
    33         if (ans==0) printf("%d
    ",2); else printf("%d
    ",1);
    34     }
    35     return 0;
    36 }

    Problem B:

    这题好像是个计算几何啊。。。不做不做(这是virtual participate时候的我),啊哼>_<

    其实这题很好做啊,把矩形之间两两最短距离细节全部判出来,

    然后直接跑SPFA最短路不就好了嘛。

    注意细节啊~~~

    代码如下:

     1 #include <bits/stdc++.h>
     2 #define Maxn 107
     3 #define Maxm 200007
     4 #define inf 1500000007
     5 using namespace std;
     6 int read()
     7 {
     8     int x=0,f=1;char ch=getchar();
     9     while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
    10     while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    11     return x*f;
    12 }
    13 int T,n,L,R,cnt,s,t;
    14 int d[Maxn],h[Maxn],k[Maxn],w[Maxn];
    15 int pre[Maxm],other[Maxm],last[Maxm];
    16 int que[Maxm*2];
    17 double dis[Maxn],len[Maxm];
    18 bool vis[Maxn];
    19 void insert(int u,int v,double d)
    20 {
    21     other[++cnt]=v,pre[cnt]=last[u],last[u]=cnt,len[cnt]=d;
    22     other[++cnt]=u,pre[cnt]=last[v],last[v]=cnt,len[cnt]=d;
    23 }
    24 void spfa()
    25 {
    26     int lx=0,rx=1;
    27     memset(vis,false,sizeof(vis));
    28     vis[s]=true;
    29     for (int i=1;i<=t;i++) dis[i]=inf*1.0;
    30     que[1]=s;
    31     while (lx<rx)
    32     {
    33         int u=que[++lx];
    34         for (int q=last[u];q;q=pre[q])
    35         {
    36             int v=other[q];
    37             if (dis[v]>dis[u]+len[q])
    38             {
    39                 dis[v]=dis[u]+len[q];
    40                 if (!vis[v])
    41                 {
    42                     vis[v]=true;
    43                     que[++rx]=v;
    44                 }
    45             }
    46         }
    47         vis[u]=false;
    48     }
    49 }
    50 int main()
    51 {
    52     freopen("street.in","r",stdin);
    53     T=read();
    54     while (T--)
    55     {
    56         n=read(),L=read(),R=read();
    57         for (int i=1;i<=n;i++)
    58             h[i]=read(),w[i]=read(),d[i]=read(),k[i]=read();
    59         cnt=0;
    60         memset(last,0,sizeof(last));
    61         s=0,t=n+1;
    62         insert(s,t,1.0*L);
    63         for (int i=1;i<=n;i++) insert(s,i,d[i]*1.0);
    64         for (int i=1;i<=n;i++) insert(i,t,(L-h[i]-d[i])*1.0);
    65         for (int i=1;i<=n;i++)
    66             for (int j=i+1;j<=n;j++)
    67             {
    68                 int dely=abs(d[j]+h[j]-d[i]);
    69                 dely=min(dely,abs(d[i]+h[i]-d[j]));
    70                 if (k[i]!=k[j]&&d[i]+h[i]>=d[j]&&d[i]+h[i]<=d[j]+h[j]) dely=0;
    71                 if (k[i]!=k[j]&&d[j]+h[j]>=d[i]&&d[j]+h[j]<=d[i]+h[i]) dely=0;
    72                 if (k[i]==k[j]||w[i]+w[j]>=R) insert(i,j,dely*1.0); else
    73                 {
    74                     int delx=R-w[i]-w[j];
    75                     insert(i,j,(double)sqrt(1LL*dely*dely+1LL*delx*delx));
    76                 }
    77             }
    78         spfa();
    79         printf("%.6lf
    ",dis[t]);
    80     }
    81     fclose(stdin);
    82     return 0;
    83 }

    Problem D:

    组合数会不会呀~~~

    写程序会不会呀~~~(捂脸熊)

    代码如下:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 int T,n,m;
     4 long long pre[25];
     5 int main()
     6 {
     7     freopen("popcorn.in","r",stdin);
     8     cin>>T;
     9     pre[1]=1;
    10     for (int i=2;i<=20;i++) pre[i]=1LL*pre[i-1]*i;
    11     while (T--)
    12     {
    13         cin>>n>>m;
    14         long long ans=1;
    15         for (int i=n-m+1;i<=n;i++) ans=1LL*ans*i;
    16         ans=ans/pre[m];
    17         cout << ans << endl;
    18     }
    19     return 0;
    20 }

    Problem E:

    这题时间限制辣么长,是不是可以暴力大搜索啊~(当然不行。。。)

    我们对于每一个点i,将i和i-di和i+di分别连边,然后直接SPFA最短路就行了。

    (其实这题我的第一反应是DP呢。。。)

    代码如下:

     1 #include <bits/stdc++.h>
     2 #define Maxn 100007
     3 #define Maxm 1000007
     4 #define inf 1000000007
     5 using namespace std;
     6 int read()
     7 {
     8     int x=0,f=1;char ch=getchar();
     9     while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
    10     while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    11     return x*f;
    12 }
    13 int T,n,cnt;
    14 int d[Maxn];
    15 int last[Maxm],pre[Maxm],other[Maxm],dis[Maxn],que[Maxm];
    16 bool vis[Maxn];
    17 void insert(int u,int v)
    18 {
    19     other[++cnt]=v,pre[cnt]=last[u],last[u]=cnt;
    20 }
    21 void spfa()
    22 {
    23     memset(que,0,sizeof(que));
    24     for (int i=1;i<=n;i++) dis[i]=inf;
    25     dis[n]=0;
    26     int lx=0,rx=1;
    27     vis[n]=true;
    28     que[1]=n;
    29     while (lx<rx)
    30     {
    31         int u=que[++lx];
    32         vis[u]=false;
    33         for (int q=last[u];q;q=pre[q])
    34         {
    35             int v=other[q];
    36             if (dis[v]>dis[u]+1)
    37             {
    38                 dis[v]=dis[u]+1;
    39                 if (!vis[v])
    40                 {
    41                     vis[v]=true;
    42                     que[++rx]=v;
    43                 }
    44             }
    45         }
    46     }
    47 }
    48 int main()
    49 {
    50     freopen("jumping.in","r",stdin);
    51     T=read();
    52     while (T--)
    53     {
    54         n=read();
    55         memset(last,0,sizeof(last));
    56         for (int i=1;i<=n;i++) d[i]=read();
    57         cnt=0;
    58         for (int i=1;i<n;i++)
    59         {
    60             if (i+d[i]<=n) insert(i+d[i],i);
    61             if (i-d[i]>0) insert(i-d[i],i);
    62         }
    63         spfa();
    64         for (int i=1;i<=n;i++)
    65             if (dis[i]<=inf/3) printf("%d
    ",dis[i]); else printf("%d
    ",-1);
    66     }
    67     return 0;
    68 }

    Problem G:

    这题的答案就是第二类斯特林数再乘上一个阶乘就好了,

    然后稍微与处理一下就好了的吧。。。

    代码如下:

     1 #include <bits/stdc++.h>
     2 #define modp 1000000007
     3 using namespace std;
     4 int read()
     5 {
     6     int x=0,f=1;char ch=getchar();
     7     while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
     8     while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
     9     return x*f;
    10 }
    11 int T,n,k;
    12 long long f[1007][1007],pre[1007];
    13 int main()
    14 {
    15     freopen("galactic.in","r",stdin);
    16     T=read();
    17     memset(f,0,sizeof(f));
    18     f[0][0]=1;
    19     for (int i=1;i<=1000;i++)
    20     {
    21         f[i][i]=1;
    22         for (int j=1;j<=i;j++)
    23             f[i][j]=(1LL*j*f[i-1][j]+f[i-1][j-1])%modp;
    24     }
    25     pre[1]=1;
    26     for (int i=2;i<=1000;i++) pre[i]=(1LL*pre[i-1]*i)%modp;
    27     while (T--)
    28     {
    29         n=read(),k=read();
    30         if (k>n) printf("%d
    ",0); else printf("%d
    ",(1LL*pre[k]*f[n][k])%modp);
    31     }
    32     return 0;
    33 }

    Problem H:

    这题不是10*10*10的DP一下就好了嘛。。。

    代码如下:

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 int read()
     4 {
     5     int x=0,f=1;char ch=getchar();
     6     while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
     7     while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
     8     return x*f;
     9 }
    10 int T,n,w[15][15][15],f[15][15][15];
    11 int main()
    12 {
    13     freopen("commandos.in","r",stdin);
    14     T=read();
    15     while (T--)
    16     {
    17         n=read();
    18         memset(w,0,sizeof(w));
    19         memset(f,0,sizeof(f));
    20         for (int i=1;i<=n;i++)
    21         {
    22             int f=read(),y=read(),x=read(),h=read();
    23             w[f][y][x]=h;
    24         }
    25         for (int i=10;i;i--)
    26             for (int j=1;j<=10;j++)
    27                 for (int k=1;k<=10;k++)
    28                 {
    29                     f[i][j][k]=max(f[i+1][j][k], max(f[i][j-1][k],f[i][j][k-1]))+w[i][j][k];
    30                 }
    31         printf("%d
    ",f[1][10][10]);
    32     }
    33     return 0;
    34 }

    Problem I:

    这题是个可做的计算几何呢~~~

    首先我们把每个圆与x轴的交点都预处理出来,

    然后排个序,类似扫描线的从左到右扫一遍就行了。

    代码如下:

     1 #include <bits/stdc++.h>
     2 #define Maxn 100007
     3 using namespace std;
     4 int read()
     5 {
     6     int x=0,f=1;char ch=getchar();
     7     while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
     8     while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
     9     return x*f;
    10 }
    11 int T,n,R,cnt;
    12 pair <double,int> s[2*Maxn];
    13 int main()
    14 {
    15     freopen("walk.in","r",stdin);
    16     T=read();
    17     while (T--)
    18     {
    19         n=read(),R=read();
    20         cnt=0;
    21         for (int i=1;i<=n;i++)
    22         {
    23             int x=read(),y=read(),r=read();
    24             if (!(r>R||y>R-r||y<r-R))
    25             {
    26                 double dis=sqrt(1.0*(R-r)*(R-r)-1.0*y*y);
    27                 s[++cnt]=make_pair(-1.0*dis+1.0*x,-r);
    28                 s[++cnt]=make_pair(1.0*dis+1.0*x,r);
    29             }
    30         }
    31         sort(s+1,s+cnt+1);
    32         long long ans=0,now=0;
    33         for (int i=1;i<=cnt;i++)
    34         {
    35             now+=s[i].second;
    36             ans=max(ans,-now);
    37         }
    38         cout<<ans<<endl;
    39     }
    40     return 0;
    41 }

    Problem J:

    为什么你们这个题都会做啊,我就不会。。。

    我们对整个树做一下DFS,然后在DFS的时候动态维护出当前的路径,

    对于当前的节点我们考虑它对答案的贡献度,

    然后发现其实只要在路径上二分以下就做完了。

    代码如下:

     1 #include <bits/stdc++.h>
     2 #define Maxn 1000007
     3 using namespace std;
     4 int read()
     5 {
     6     int x=0,f=1;char ch=getchar();
     7     while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
     8     while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
     9     return x*f;
    10 }
    11 int T,n,cnt;
    12 int val[Maxn];
    13 long long path[Maxn],ans[Maxn],depth[Maxn];
    14 int pre[Maxn],other[Maxn],last[Maxn],len[Maxn];
    15 int father[Maxn];
    16 void insert(int u,int v,int dis)
    17 {
    18     other[++cnt]=v,pre[cnt]=last[u],len[cnt]=dis,last[u]=cnt;
    19 }
    20 void dfs(int u,int fa,int num)
    21 {
    22     for (int q=last[u];q;q=pre[q])
    23     {
    24         int v=other[q];
    25         if (v!=fa)
    26         {
    27             father[v]=u;
    28             path[num]=v;
    29             depth[num]=depth[num-1]+len[q];
    30             int pos=lower_bound(depth,depth+num+1,depth[num]-val[v])-depth;
    31             if (pos<num)
    32             {
    33                 ++ans[u];
    34                 --ans[father[path[pos]]];
    35             }
    36             dfs(v,u,num+1);
    37             ans[u]+=ans[v];
    38         }
    39     }
    40 }
    41 int main()
    42 {
    43     freopen("car.in","r",stdin);
    44     T=read();
    45     while (T--)
    46     {
    47         n=read(),cnt=0;
    48         memset(last,0,sizeof(last));
    49         for (int i=1;i<=n;i++) val[i]=read();
    50         for (int i=1;i<n;i++)
    51         {
    52             int u=read(),v=read(),dis=read();
    53             insert(u,v,dis),insert(v,u,dis);
    54         }
    55         memset(depth,0,sizeof(depth));
    56         memset(path,0,sizeof(path));
    57         memset(ans,0,sizeof(ans));
    58         path[0]=1,depth[0]=0;
    59         dfs(1,-1,1);
    60         for (int i=1;i<=n;i++) printf("%lld ",ans[i]);
    61         printf("
    ");
    62     }
    63     return 0;
    64 }
  • 相关阅读:
    权限设计=功能权限+数据权限
    C# 自定义配置文件
    asp.net core 系列 2 启动类 Startup.CS
    asp.net core 系列 1 概述
    IOC : Unity 配置和使用
    Unity Ioc 依赖倒置及Untity AOP被动拦截/自动拦截
    webuploader-异步切片上传(暂不支持断点续传)及 下载方法!C#/.NET
    C# 构造基础返回值类型-BaseResponse
    神奇的选择器 :focus-within
    妙用 scale 与 transfrom-origin,精准控制动画方向
  • 原文地址:https://www.cnblogs.com/Tommyr7/p/6761770.html
Copyright © 2011-2022 走看看