• 2018北京师范大学第十六届程序设计竞赛决赛


    A   塞特斯玛斯塔 > 25987787

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cmath>
     4 #include <cstring>
     5 #include <string>
     6 #include <set>
     7 #include <map>
     8 #include <list>
     9 #include <stack>
    10 #include <queue>
    11 #include <vector>
    12 #include <algorithm>
    13 #include <iostream>
    14 using namespace std;
    15 #define ll long long
    16 #define inf 1e9
    17 const long maxn=1e5+5;
    18 const ll mod=1e9+7;
    19  
    20 int main()
    21 {
    22     char s[20];
    23     bool vis;
    24     long t,n;
    25     scanf("%ld",&t);
    26     while (t--)
    27     {
    28         scanf("%ld",&n);
    29         vis=true;
    30         while (n--)
    31         {
    32             scanf("%s",s);
    33             if (strcmp(s,"PERFECT")!=0)
    34                 vis=false;
    35         }
    36         if (vis)
    37             printf("MILLION Master
    ");
    38         else
    39             printf("NAIVE Noob
    ");
    40     }
    41     return 0;
    42 }

    B   外挂使用拒绝 > 25996775

    求C(k,i)。k太大,i<=n,n较小。

    解题报告的矩阵有点意思。

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cmath>
     4 #include <cstring>
     5 #include <string>
     6 #include <set>
     7 #include <map>
     8 #include <list>
     9 #include <stack>
    10 #include <queue>
    11 #include <vector>
    12 #include <algorithm>
    13 #include <iostream>
    14 using namespace std;
    15 #define ll long long
    16 #define inf 1e9
    17 const long maxn=1e4+5;
    18 const ll mod=1e9+7;
    19  
    20 ll a[maxn],b[maxn],x[maxn],c[maxn];
    21  
    22 ll ni(ll a)
    23 {
    24     long ci=mod-1-1;
    25     ll r=1;
    26     while (ci)
    27     {
    28         if (ci & 1)
    29             r=r*a%mod;
    30         a=a*a%mod;
    31         ci>>=1;
    32     }
    33     return r;
    34 }
    35  
    36 int main()
    37 {
    38     long t,n,m,i,j;
    39     ll ans,d;
    40     a[1]=1;
    41     for (i=2;i<=1e3;i++)
    42         a[i]=a[i-1]*i%mod;
    43     b[1000]=ni(a[1000]);
    44     for (i=1e3-1;i>=1;i--)
    45         b[i]=b[i+1]*(i+1)%mod;
    46     b[0]=1;
    47     scanf("%ld",&t);
    48     while (t--)
    49     {
    50         scanf("%ld%ld",&n,&m);
    51         for (i=0;i<n;i++)
    52             scanf("%lld",&x[i]);
    53         d=1;
    54         for (i=0;i<=min(m,n);i++)
    55         {
    56             c[i]=d%mod*b[i]%mod;
    57             d=d*(m-i)%mod;
    58         }
    59         for (i=0;i<n;i++)
    60         {
    61             ans=0;
    62             for (j=0;j<=min(i,m);j++)
    63                 if (j & 1)
    64                     ans=(ans-c[j]*x[i-j])%mod;
    65                 else
    66                     ans=(ans+c[j]*x[i-j])%mod;
    67             printf("%lld",(ans%mod+mod)%mod);
    68  
    69             if (i==n-1)
    70                 printf("
    ");
    71             else
    72                 printf(" ");
    73         }
    74     }
    75     return 0;
    76 }

    C   萌萌哒身高差  > 25989150  

    比赛时是找规律的。

    现证:

    相邻点对(i,j)、(j,i)出现次数:把i,j / j,i 看成一个整体,即P(n-1,n-1)=(n-1)!

    (1,1),(1,2),……,(n-1,n)的差值为1,1,2,1,2,3,……

    总排列次数:n!

    (n-1)!*2 * (1 + 1+2 + 1+2+3 + … + 1+2+…+n) / n!

    =( 1*2+2*3+…+n*(n+1) )/n/3 = (n*(n+1)*(n+2)-0*1*2)/3 = (n-1)(n+1)/3

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cmath>
     4 #include <cstring>
     5 #include <string>
     6 #include <set>
     7 #include <map>
     8 #include <list>
     9 #include <stack>
    10 #include <queue>
    11 #include <vector>
    12 #include <algorithm>
    13 #include <iostream>
    14 using namespace std;
    15 #define ll long long
    16 #define inf 1e9
    17 const long maxn=1e5+5;
    18 const ll mod=1e9+7;
    19  
    20 long a[10],ans=0,n=5;
    21  
    22 void dfs(long i)
    23 {
    24     if (i==n)
    25     {
    26         for (i=1;i<n;i++)
    27             ans+=abs(a[i+1]-a[i]);
    28         return;
    29     }
    30     dfs(i+1);
    31     long j,t;
    32     for (j=i+1;j<=n;j++)
    33     {
    34         t=a[i];
    35         a[i]=a[j];
    36         a[j]=t;
    37         dfs(i+1);
    38         t=a[i];
    39         a[i]=a[j];
    40         a[j]=t;
    41     }
    42 }
    43  
    44 int main()
    45 {
    46     long i,j=1,t,n;
    47 //    for (n=1;n<=10;n++)
    48 //    {
    49 //        ans=0;
    50 //        for (i=1;i<=n;i++)
    51 //            a[i]=i;
    52 //        dfs(1);
    53 //        j=j*n;
    54 //        printf("%ld %ld %f
    ",ans,j,1.0*ans/j);
    55 //    }
    56     scanf("%ld",&t);
    57     while (t--)
    58     {
    59         scanf("%ld",&n);
    60         printf("%.13f
    ",1.0*(n*n-1)/3);
    61     }
    62     return 0;
    63 }

    D   雷电爆裂之力 > 25992094

    一开始以为求三段最短路,仔细看发现最左边和最右边到达的位置任意,即可只用求中间两部分。妙题。

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cmath>
     4 #include <cstring>
     5 #include <string>
     6 #include <set>
     7 #include <map>
     8 #include <list>
     9 #include <stack>
    10 #include <queue>
    11 #include <vector>
    12 #include <algorithm>
    13 #include <iostream>
    14 using namespace std;
    15 #define ll long long
    16 #define inf 1e9
    17 const long maxn=1e5+5;
    18 const ll mod=1e9+7;
    19  
    20 ll a[maxn],b[maxn],c[maxn];
    21  
    22 int main()
    23 {
    24     long t,n,m,p,i,j,k;
    25     ll r;
    26     scanf("%ld",&t);
    27     while (t--)
    28     {
    29         scanf("%ld%ld%ld",&n,&m,&p);
    30         for (i=1;i<=n;i++)
    31             scanf("%lld",&a[i]);
    32         for (i=1;i<=m;i++)
    33             scanf("%lld",&b[i]);
    34         for (i=1;i<=p;i++)
    35             scanf("%lld",&c[i]);
    36         a[0]=-10*inf-1; c[0]=-10*inf-1;
    37         a[n+1]=10*inf+1; c[p+1]=10*inf+1;
    38         sort(a+1,a+n+1);
    39         sort(b+1,b+m+1);
    40         sort(c+1,c+p+1);
    41         i=0; k=0; r=(ll)10*inf;
    42         for (j=1;j<=m;j++)
    43         {
    44             while (i!=n && a[i+1]<=b[j])
    45                 i++;
    46             while (k!=p && c[k+1]<=b[j])
    47                 k++;
    48             r=min(r,min(b[j]-a[i],a[i+1]-b[j]) + min(b[j]-c[k],c[k+1]-b[j]));
    49         }
    50         printf("%lld
    ",r+3);
    51     }
    52     return 0;
    53 }
    54 /*
    55 3 3 3
    56 -5 -4 -3
    57 0 1 2
    58 5 4 3
    59 */

    E   可以来拯救吗 > 26006992

    比赛时想到dfs,但没想到dfs能过。。。

    "

    一个trick 是,n 和k 都可能很大,比如
    n = 100000; k = 99999,此时正常的枚举子序列会严重超时。解
    决办法是当k > n/2 时,令k = n - k,然后枚举反面即可。

    "

    为什么 n = 100000; k = 99999时 超时:

    采用dfs,如1~6:2,3,4,5,6(2,3,4,5,6); 1,3,4,5,6(3,4,5,6) ; 1,2,4,5,6(4,5,6) ; 1,2,3,5,6(5,6) ; 1,2,3,4,6(6); 1,2,3,4,5,括号里的内容都要单独计算。dfs的优势是很多内容不必重复计算,但这里并不明显。如n=100000,对于括号里的内容,计算量约为n*n/2,超时。

    get~

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cmath>
     4 #include <cstring>
     5 #include <string>
     6 #include <set>
     7 #include <map>
     8 #include <list>
     9 #include <stack>
    10 #include <queue>
    11 #include <vector>
    12 #include <algorithm>
    13 #include <iostream>
    14 using namespace std;
    15 #define ll long long
    16 #define inf 1e9
    17 const long maxn=1e5+5;
    18 const ll mod=1e9+7;
    19  
    20 long a[maxn],n,g,m,mode,total;
    21 ll r;
    22  
    23 //ith jGe ansValue
    24 void dfs(long i,long j,long ans)
    25 {
    26     if (j==g)
    27     {
    28         if (mode)
    29             r=r ^ ((ll)(total-ans)*(total-ans));
    30         else
    31             r=r ^ ((ll)ans*ans);
    32         return;
    33     }
    34     if (i==n+1)
    35         return;
    36 //    if (g-j<=n-i) //i=3 j=1 g=2 n=4
    37     if (i-j<=m)
    38         dfs(i+1,j,ans);
    39     dfs(i+1,j+1,ans+a[i]);
    40 }
    41  
    42 int main()
    43 {
    44     long t,i;
    45     scanf("%ld",&t);
    46     while (t--)
    47     {
    48         scanf("%ld%ld",&n,&g);
    49         for (i=1;i<=n;i++)
    50             scanf("%ld",&a[i]);
    51         if (g>n/2)
    52         {
    53             mode=1;
    54             total=0;
    55             for (i=1;i<=n;i++)
    56                 total+=a[i];
    57             g=n-g;
    58         }
    59         else
    60             mode=0;
    61         r=0;
    62         m=n-g;
    63         dfs(1,0,0);
    64         printf("%lld
    ",r);
    65     }
    66     return 0;
    67 }

    F   汤圆防漏理论 > 26002436

    贪心

    set维护,get~

    set:多个关键字(pair),默认从第一关键字开始,从大到小排序(不用像优先队列,要自己写函数)

    可删除固定值的点,这是优先队列无法做到的,优先队列只能增加修改过的点(值变小),而set可以删除之前的点,再增加修改过的点,使数目不会增加。

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cmath>
     4 #include <cstring>
     5 #include <string>
     6 #include <set>
     7 #include <map>
     8 #include <list>
     9 #include <stack>
    10 #include <queue>
    11 #include <vector>
    12 #include <algorithm>
    13 #include <iostream>
    14 using namespace std;
    15 #define ll long long
    16 #define inf 1e9
    17 const long maxn=1e5+5;
    18 const ll mod=1e9+7;
    19  
    20 vector<pair<long,ll> > e[maxn];
    21 set<pair<ll,long> > f;
    22 ll dist[maxn];
    23  
    24 bool vis[maxn];
    25  
    26 int main()
    27 {
    28     long t,x,y,n,m,d,dd,i;
    29     ll r,z;
    30     vector<pair<long,ll> >::iterator j;
    31     scanf("%ld",&t);
    32     while (t--)
    33     {
    34         scanf("%ld%ld",&n,&m);
    35         for (i=1;i<=n;i++)
    36         {
    37             dist[i]=0;
    38             vis[i]=0;
    39             e[i].clear();
    40         }
    41         while (m--)
    42         {
    43             scanf("%ld%ld%lld",&x,&y,&z);
    44             e[x].push_back({y,z}); //make_pair
    45             e[y].push_back({x,z});
    46             dist[x]+=z;
    47             dist[y]+=z;
    48         }
    49         f.clear();
    50         for (i=1;i<=n;i++)
    51             f.insert({dist[i],i});
    52  
    53         //set sort first(降序)
    54         r=0;
    55         for (i=1;i<=n;i++)
    56         {
    57             r=max(r,f.begin()->first);
    58             d=f.begin()->second;
    59             vis[d]=true;
    60             f.erase(f.begin());
    61             for (j=e[d].begin();j!=e[d].end();j++)
    62             {
    63                 dd=j->first;
    64                 if (vis[dd]) continue;
    65                 f.erase({dist[dd],dd});
    66                 dist[dd]-=j->second;
    67                 f.insert({dist[dd],dd});
    68             }
    69         }
    70         printf("%lld
    ",r);
    71     }
    72     return 0;
    73 }

    不知以下程序哪里错了(优先队列):

      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <cmath>
      4 #include <cstring>
      5 #include <string>
      6 #include <set>
      7 #include <map>
      8 #include <list>
      9 #include <stack>
     10 #include <queue>
     11 #include <vector>
     12 #include <algorithm>
     13 #include <iostream>
     14 using namespace std;
     15 #define ll long long
     16 #define inf 1e9
     17 const long maxn=1e5+5;
     18 const ll mod=1e9+7;
     19  
     20 struct node
     21 {
     22     long d;
     23     ll len;
     24     struct node *next;
     25 }*point[maxn];
     26 ll dist[maxn];
     27  
     28 struct cmp
     29 {
     30     bool operator() (int a,int b)
     31     {
     32         return dist[a]>dist[b];
     33     }
     34 };
     35  
     36 priority_queue<int,vector<int>,cmp > f;
     37 bool vis[maxn];
     38  
     39 int main()
     40 {
     41     struct node *p;
     42     long t,x,y,n,m,d,i;
     43     ll r,z;
     44     scanf("%ld",&t);
     45     while (t--)
     46     {
     47         scanf("%ld%ld",&n,&m);
     48         for (i=1;i<=n;i++)
     49         {
     50             dist[i]=0;
     51             point[i]=NULL;
     52             vis[i]=0;
     53         }
     54         while (m--)
     55         {
     56             scanf("%ld%ld%lld",&x,&y,&z);
     57             p=(struct node *) malloc (sizeof(struct node));
     58             p->d=y;
     59             p->len=z;
     60             p->next=point[x];
     61             point[x]=p;
     62  
     63             p=(struct node *) malloc (sizeof(struct node));
     64             p->d=x;
     65             p->len=z;
     66             p->next=point[y];
     67             point[y]=p;
     68  
     69             dist[x]=dist[x]+z;
     70             dist[y]=dist[y]+z;
     71         }
     72         r=0;
     73         while (!f.empty())
     74             f.pop();
     75         for (i=1;i<=n;i++)
     76             if (dist[i]>0)
     77                 f.push(i);
     78         while (!f.empty())
     79         {
     80             d=f.top();
     81             r=max(r,dist[d]);
     82             vis[d]=1;
     83             f.pop();
     84  
     85             p=point[d];
     86             while (p)
     87             {
     88                 if (!vis[p->d])
     89                 {
     90                     dist[p->d]=dist[p->d]-p->len;
     91                     f.push(p->d);
     92                 }
     93                 p=p->next;
     94             }
     95             while (!f.empty() && vis[f.top()])
     96                 f.pop();
     97         }
     98         printf("%lld
    ",r);
     99     }
    100     return 0;
    101 }

    G   命名规范问题 > 25988482

    模拟

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cmath>
     4 #include <cstring>
     5 #include <string>
     6 #include <set>
     7 #include <map>
     8 #include <list>
     9 #include <stack>
    10 #include <queue>
    11 #include <vector>
    12 #include <algorithm>
    13 #include <iostream>
    14 using namespace std;
    15 #define ll long long
    16 #define inf 1e9
    17 const long maxn=1e5+5;
    18 const ll mod=1e9+7;
    19  
    20 int main()
    21 {
    22     long t,i,j,k,g;
    23     bool vis;
    24     char s[30],str[50];
    25     scanf("%ld",&t);
    26     while (t--)
    27     {
    28         scanf("%s",s);
    29         g=0;
    30         j=-100;
    31         k=0;
    32         vis=true;
    33         strcpy(str,"");
    34         for (i=0;i<strlen(s);i++)
    35             if ((s[i]>='A' && s[i]<='Z') || i==0)
    36             {
    37                 g++;
    38                 if (i-j<2)
    39                     vis=false;
    40                 j=i;
    41                 if (g>1)
    42                 {
    43                     str[k]='_';
    44                     k++;
    45                 }
    46                 if (s[i]>='A' && s[i]<='Z')
    47                 {
    48                     str[k]=s[i]+32;
    49                     k++;
    50                 }
    51                 else
    52                 {
    53                     str[k]=s[i];
    54                     k++;
    55                 }
    56             }
    57             else
    58             {
    59                 str[k]=s[i];
    60                 k++;
    61             }
    62         str[k]='';
    63         if (i-j<2 || g<2)
    64             vis=false;
    65         if (vis)
    66             printf("%s
    ",str);
    67         else
    68             printf("%s
    ",s);
    69     }
    70     return 0;
    71 }

    I   如何办好比赛 > 25988103

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cmath>
     4 #include <cstring>
     5 #include <string>
     6 #include <set>
     7 #include <map>
     8 #include <list>
     9 #include <stack>
    10 #include <queue>
    11 #include <vector>
    12 #include <algorithm>
    13 #include <iostream>
    14 using namespace std;
    15 #define ll long long
    16 #define inf 1e9
    17 const long maxn=1e5+5;
    18 const ll mod=1e9+7;
    19  
    20 int main()
    21 {
    22     long n,i,t;
    23     ll ans,g,k,y;
    24     char c;
    25     scanf("%ld",&t);
    26     while (t--)
    27     {
    28         scanf("%ld%lld
    ",&n,&k);
    29         g=0;
    30         ans=0;
    31         for (i=0;i<n;i++)
    32         {
    33             scanf("%c",&c);
    34             if (c=='D')
    35                 g++;
    36             else
    37                 ans=ans+g;
    38         }
    39         y=g*(n-g);
    40         if (k>y)
    41             printf("-1
    ");
    42         else
    43             printf("%lld
    ",abs(ans-k));
    44     }
    45     return 0;
    46 }

    J   小白兔小灰兔 > 26005070

    求的是简单多边形,包括凸多边形和凹多边形。

    若只是凸多边形,可以比对边斜率 和 太阳点与边点的斜率 ,得到两个边界点。

    以下程序不知道哪里错了

      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <cmath>
      4 #include <cstring>
      5 #include <string>
      6 #include <set>
      7 #include <map>
      8 #include <list>
      9 #include <stack>
     10 #include <queue>
     11 #include <vector>
     12 #include <algorithm>
     13 #include <iostream>
     14 using namespace std;
     15 #define ll long long
     16 #define inf 1e9
     17 const long maxn=1e1+5;
     18 const ll mod=1e9+7;
     19  
     20 struct Point
     21 {
     22     double x,y;
     23 }p[maxn],A,B;
     24  
     25 bool lineIntersectSide(Point A,Point B,Point C,Point D)
     26 {
     27     double fC=(C.y-A.y)*(A.x-B.x)-(C.x-A.x)*(A.y-B.y);
     28     double fD=(D.y-A.y)*(A.x-B.x)-(D.x-A.x)*(A.y-B.y);
     29     if (fC*fD>0)
     30         return 0;
     31     return 1;
     32 }
     33  
     34 bool sideIntersectSide(Point A,Point B,Point C,Point D)
     35 {
     36     if (!lineIntersectSide(A,B,C,D))
     37         return 0;
     38     if (!lineIntersectSide(C,D,A,B))
     39         return 0;
     40     return 1;
     41 }
     42  
     43 int main()
     44 {
     45     long t,n,i,j,nexti,nextj;
     46     double ans;
     47     bool vis;
     48     scanf("%ld",&t);
     49     while (t--)
     50     {
     51         scanf("%ld",&n);
     52         for (i=0;i<n;i++)
     53             scanf("%lf%lf",&p[i].x,&p[i].y);
     54         scanf("%lf%lf",&A.x,&A.y);
     55         //p[i] p[i+1] line
     56         ans=0;
     57         for (i=0;i<n;i++)
     58         {
     59             nexti=(i+1)%n;
     60             B.x=(p[i].x+p[nexti].x)/2.0;
     61             B.y=(p[i].y+p[nexti].y)/2.0;
     62  
     63             j=nexti;
     64             vis=true;
     65             while (j!=i)
     66             {
     67                 //p[j] p[j+1]
     68                 nextj=(j+1)%n;
     69                 if (sideIntersectSide(A,B,p[j],p[nextj]))
     70                 {
     71                     vis=false;
     72                     break;
     73                 }
     74                 j=nextj;
     75             }
     76             if (vis)
     77                 ans+=sqrt((p[i].x-p[nexti].x)*(p[i].x-p[nexti].x) + (p[i].y-p[nexti].y)*(p[i].y-p[nexti].y));
     78         }
     79         printf("%.13f
    ",ans);
     80     }
     81     return 0;
     82 }
     83 /*
     84 10
     85 4
     86 0 0
     87 1 0
     88 1 2
     89 0 1
     90 1 3
     91  
     92 4
     93 0 0
     94 1 0
     95 1 2
     96 0 1
     97 2 3
     98  
     99 4
    100 0 0
    101 1 0
    102 1 2
    103 0 1
    104 2 4
    105  
    106 5
    107 0 0
    108 8 0
    109 5 2
    110 4 1
    111 3 2
    112 3 10
    113  
    114 6
    115 2 0
    116 4 0
    117 6 2
    118 4 4
    119 2 4
    120 0 2
    121 3 5
    122  
    123 6
    124 2 0
    125 4 0
    126 6 2
    127 4 4
    128 2 4
    129 0 2
    130 -100 -100
    131  
    132 6
    133 2 0
    134 4 0
    135 6 2
    136 4 4
    137 2 4
    138 0 2
    139 0 0
    140  
    141 3
    142 0 0
    143 2 0
    144 2 2
    145 4 4
    146  
    147 3
    148 0 0
    149 2 0
    150 2 2
    151 0 2
    152  
    153 3
    154 0 0
    155 2 0
    156 2 2
    157 3 4
    158  
    159 3
    160 0 0
    161 3 0
    162 2 2
    163 5 5
    164  
    165 3
    166 0 0
    167 3 0
    168 2 2
    169 5 6
    170  
    171 3
    172 0 0
    173 3 0
    174 2 2
    175 5 4
    176  
    177 3
    178 0 0
    179 3 0
    180 2 2
    181 5 0
    182  
    183 3
    184 0 0
    185 3 0
    186 2 2
    187 -5 0
    188 */

    Solution Offical:

    https://pan.baidu.com/s/1oHvCp1G_xzpRSH5-HAmXXQ

  • 相关阅读:
    函数嵌套 lisp表达式求值
    初涉时间间隔问题
    高精度算法-带小数大数相加
    12/10 C语言程序设计竞赛 后五题
    字符串头尾连接问题-木棒连接
    ZJGSU-ACM OJ 心得
    高精度算法-大数乘法
    趣味两题-(简单追及问题、两直线相交问题)
    struts2基于注解的action
    spring中常用的注解
  • 原文地址:https://www.cnblogs.com/cmyg/p/8969668.html
Copyright © 2020-2023  润新知