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\n");
38         else
39             printf("NAIVE Noob\n");
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("\n");
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\n",ans,j,1.0*ans/j);
55 //    }
56     scanf("%ld",&t);
57     while (t--)
58     {
59         scanf("%ld",&n);
60         printf("%.13f\n",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\n",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\n",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\n",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\n",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]='\0';
63         if (i-j<2 || g<2)
64             vis=false;
65         if (vis)
66             printf("%s\n",str);
67         else
68             printf("%s\n",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",&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\n");
42         else
43             printf("%lld\n",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\n",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

 

posted @ 2018-04-28 21:35  congmingyige  阅读(322)  评论(0编辑  收藏  举报