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时 超时:
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