百度之星2020 初赛三场 部分题解

初赛一:

1001 Drink:$maxleft{leftlceilfrac{m}{x} ight ceilcdot y ight}$

 1 #include<cstdio>
 2 #include<algorithm>
 3 #define rep(i, l, r) for (int i = (l); i <= (r); i++)
 4 using namespace std;
 5 
 6 int T, n, m, x, y;
 7 
 8 int main(){
 9     freopen("drink.in", "r", stdin);
10     freopen("drink.out", "w", stdout);
11     for (scanf("%d", &T); T--; ) {
12         scanf("%d%d", &n, &m); int ans = 1e8;
13         rep(i, 1, n) scanf("%d%d", &x, &y), ans = min(ans, ((m - 1) / x + 1) * y);
14         printf("%d
", ans);
15     }
16     return 0;
17 }
Drink

1002 GPA:模拟DP。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #define rep(i, l, r) for (int i = (l); i <= (r); i++)
 4 using namespace std;
 5 
 6 int T, n;
 7 double f[500];
 8 
 9 double G(int x) {
10     if (x >= 95) return 4.3;
11     if (x >= 90) return 4.0;
12     if (x >= 85) return 3.7;
13     if (x >= 80) return 3.3;
14     if (x >= 75) return 3.0;
15     if (x >= 70) return 2.7;
16     if (x >= 67) return 2.3;
17     if (x >= 65) return 2.0;
18     if (x >= 62) return 1.7;
19     if (x >= 60) return 1.0;
20     return 0;
21 }
22 
23 int main(){
24     freopen("GPA.in", "r", stdin);
25     freopen("GPA.out", "w", stdout);
26     f[0]=0;
27     rep(i, 1, 400) rep(j, 1, min(i, 100))
28         f[i] = max(f[i], f[i - j] + G(j));
29     for (scanf("%d", &T); T--; )
30         scanf("%d", &n),printf("%.1lf
", f[n]);
31     return 0;
32 }
GPA

1003 Dec:先打表。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
 4 using namespace std;
 5 
 6 const int N=1050;
 7 int T,x,y,mp[N][N];
 8 
 9 int main(){
10     freopen("dec.in","r",stdin);
11     freopen("dec.out","w",stdout);
12     mp[1][1]=1;
13     rep(i,2,1000) rep(j,1,i)
14         mp[i][j]=(__gcd(i,j)==1)+max(mp[i-1][j],mp[i][j-1]);
15     for (scanf("%d",&T); T--; )
16         scanf("%d%d",&x,&y),printf("%d
",mp[max(x,y)][min(x,y)]);
17     return 0;
18 }
Dec

1004 Civilization:枚举建立城市的位置,统计附近(曼哈顿距离3以内)各a值的点各有多少个,按a从高到低一次放居民,模拟即可。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
 4 using namespace std;
 5 
 6 const int N=510;
 7 int T,n,x0,y0,ans,f[4],a[N][N];
 8 
 9 int main(){
10     freopen("1004.in","r",stdin);
11     freopen("1004.out","w",stdout);
12     for (scanf("%d",&T); T--; ){
13         scanf("%d%d%d",&n,&x0,&y0); ans=1e8;
14         rep(i,1,n) rep(j,1,n) scanf("%d",&a[i][j]);
15         rep(x,1,n) rep(y,1,n){
16             int sm=(abs(x-x0)+abs(y-y0)+1)/2,tot=0;
17             rep(i,x-3,x+3) rep(j,y-3,y+3)
18                 if (i>=1 && i<=n && j>=1 && j<=n && abs(i-x)+abs(j-y)<=3) f[a[i][j]]++;
19             int s=a[x][y]; f[s]--;
20             rep(k,1,8){
21                 int t=(8*k*k-tot-1)/s+1; sm+=t; tot+=t*s;
22                 if (f[3]) s+=3,f[3]--;
23                 else if (f[2]) s+=2,f[2]--;
24                     else if (f[1]) s+=1,f[1]--;
25             }
26             ans=min(ans,sm);
27         }
28         printf("%d
",ans);
29     }
30     return 0;
31 }
civilization

1005 内层块长必定比外层短,故内层的一块至多与外层的一块相连,而外层则不一定,故若将每个黑块看成一个点,相邻两层的相连黑块之间连边,则构成一个森林。森林的连通块数=点数-边数。点数显然,考虑边数期望。

考虑外层的一个黑块,与内层某黑块相连的概率为$frac{frac{2pi}{a_{i-1}}+frac{2pi}{a_{i}}}{2pi}=frac{1}{a_{i-1}}+frac{1}{a_{i}}$,故相邻两层边数期望为$(frac{1}{a_{i-1}}+frac{1}{a_{i}})cdotfrac{a_i}{2}cdotfrac{a_{i-1}}{2}=frac{a_i+a_{i-1}}{4}$。

最后答案化简为$frac{a_1+a_n}{4}$

 1 #include<cstdio>
 2 #include<algorithm>
 3 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
 4 typedef long long ll;
 5 using namespace std;
 6 
 7 const int N=1010,mod=1e9+7;
 8 int T,n,a[N];
 9 
10 int ksm(int a,int b){
11     int res=1;
12     for (; b; a=1ll*a*a%mod,b>>=1)
13         if (b & 1) res=1ll*res*a%mod;
14     return res;
15 }
16 
17 int main(){
18     freopen("rotate.in","r",stdin);
19     freopen("rotate.out","w",stdout);
20     for (scanf("%d",&T); T--; ){
21         scanf("%d",&n);
22         rep(i,1,n) scanf("%d",&a[i]);
23         printf("%lld
",1ll*(a[1]+a[n])*ksm(4,mod-2)%mod);
24     }
25     return 0;
26 }
rotate

初赛二:

1001 Poker:直接模拟,发现迷之错误时多换几次实数运算的写法。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
 4 using namespace std;
 5 
 6 int T,n,m,p;
 7 
 8 int main(){
 9     for (scanf("%d",&T); T--; ){
10         scanf("%d%d%d",&n,&m,&p);
11         int t=m-(int)(m*(100-p)/100.);
12         printf("%d
",(n<m)?0:((n-m)/t+1));
13     }
14     return 0;
15 }
Poker

1002 Distance:所有点必然排在一条直线上否则没法做,于是必然都在P0同侧。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
 4 typedef long long ll;
 5 using namespace std;
 6 
 7 const int N=100010;
 8 int T,n,a[N];
 9 ll ans,sm[N];
10 
11 int main(){
12     for (scanf("%d",&T); T--; ){
13         scanf("%d",&n);
14         rep(i,1,n) scanf("%d",&a[i]);
15         sort(a+1,a+n+1); sm[0]=ans=0;
16         rep(i,1,n) sm[i]=sm[i-1]+a[i];
17         rep(i,1,n-1) ans+=sm[n]-sm[i]-1ll*(n-i)*a[i];
18         printf("%lld
",ans);
19     }
20     return 0;
21 }
Distance

1003 Covid:把各事件写成<时间,地点,人>三元组用map存储,然后按时间顺序将同一时间同一地点的所有时间放在一起处理即可,线性。

 1 #include<cstdio>
 2 #include<vector>
 3 #include<algorithm>
 4 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
 5 using namespace std;
 6 
 7 const int N=20010;
 8 int T,n,m,s[N],b[N];
 9 vector<int>mp[110][11];
10 
11 int main(){
12     for (scanf("%d",&T); T--; ){
13         scanf("%d",&n); b[1]=1;
14         rep(i,2,n) b[i]=0;
15         rep(i,1,100) rep(j,1,10) mp[i][j].clear();
16         rep(i,1,n){
17             scanf("%d",&m); int t,p;
18             rep(j,1,m) scanf("%d%d",&t,&p),mp[t][p].push_back(i);
19         }
20         rep(i,1,100) rep(j,1,10){
21             int s=mp[i][j].size(),flag=0;
22             rep(k,0,s-1) if (b[mp[i][j][k]]) flag=1;
23             if (flag) rep(k,0,s-1) b[mp[i][j][k]]=1;
24         }
25         int tot=0; rep(i,1,n) if (b[i]) s[++tot]=i;
26         rep(i,1,tot-1) printf("%d ",s[i]); printf("%d
",s[tot]);
27     }
28     return 0;
29 }
Covid

1004 Car:可以DP,但bestcoder机子跑的比较快爆搜可过。DP做法设f[i][S]为前i天禁止尾号状态为S(压成二进制)的最优解,转移显然。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
 4 using namespace std;
 5 
 6 char str[10];
 7 int T,n,ans,s[20],d[20];
 8 
 9 void dfs(int x){
10     if (x==10){
11         int res=20000;
12         rep(i,1,5) res=min(res,d[i]);
13         ans=max(ans,res);
14         return;
15     }
16     rep(i,1,5) d[i]+=s[x],dfs(x+1),d[i]-=s[x];
17 }
18 
19 int main(){
20     for (scanf("%d",&T); T--; ){
21         scanf("%d",&n); ans=0;
22         rep(i,0,9) s[i]=d[i]=0;
23         rep(i,1,n) scanf("%s",str),s[str[4]-'0']++;
24         dfs(0); printf("%d
",n-ans);
25     }
26     return 0;
27 }
Car(爆搜)
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
 5 using namespace std;
 6 
 7 const int N=10010;
 8 char s[10];
 9 int n,T,p[11],a[N],d[11][N];
10 
11 int main(){
12     for (scanf("%d",&T); T--; ){
13         scanf("%d",&n);
14         rep(i,0,9) p[i]=0;
15         rep(i,1,n) scanf("%s",s+1),a[i]=s[5]-'0',p[a[i]]++;
16         memset(d,0x3f,sizeof(d)); d[0][0]=0;
17         rep(i,1,5) rep(j,0,(1<<10)-1) for (int k=j; ; k=(k-1)&j){
18             int t=j^k,sm=0;
19             rep(l,0,9) if (!((t>>l)&1)) sm+=p[l];
20             d[i][j]=min(d[i][j],max(d[i-1][k],sm));
21             if (!k) break;
22         }
23         printf("%d
",d[5][(1<<10)-1]);
24     }
25     return 0;
26 }
Car(DP)

初赛三:

1001 Discount:模拟。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
 4 using namespace std;
 5 
 6 int T,n,b;
 7 double c,ans;
 8 
 9 int main(){
10     for (scanf("%d",&T); T--; ){
11         scanf("%d",&n); ans=-1;
12         rep(i,1,n) scanf("%d%lf",&b,&c),ans=max(ans,(1-c)/(b+1-c));
13         printf("%.5lf
",ans);
14     }
15     return 0;
16 }
Discount

1002 Game:p>1则显然p=2x,否则(x/2+x*2)/2=1.25x>x,则换一定更优。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
 4 using namespace std;
 5 
 6 int T;
 7 double p;
 8 
 9 int main(){
10     for (scanf("%d",&T); T--; )
11         scanf("%lf",&p),puts((p>1)?"No":"Yes");
12     return 0;
13 }
Game

1003 Permutation:要想逆序对尽量多,就<1,n>,<2,n-1>,...分别依次交换即可。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
 4 using namespace std;
 5 
 6 int T,n,m;
 7 
 8 int main(){
 9     for (scanf("%d",&T); T--; )
10         scanf("%d%d",&n,&m),m=min(m,n/2),printf("%lld
",(n==1)?0ll:1ll*(2*n-3)*m-2ll*m*(m-1));
11     return 0;
12 }
Permutation

1004 Intersection:只考虑两列最后一辆车,左侧设为A,右侧为B。若A>B则B不挡A,答案就是A的步数。若A<=B-2则B必然比A后到达,答案为B的步数。A=B或A=B-1时答案为B的步数+1。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
 4 using namespace std;
 5 
 6 int T,n,s1,s2,x,y;
 7 
 8 int main(){
 9     for (scanf("%d",&T); T--; ){
10         scanf("%d",&n); s1=s2=0;
11         rep(i,1,n){
12             scanf("%d%d",&x,&y);
13             if (x==1) s2=max(s2,y); else s1=max(s1,y);
14         }
15         if (s1 && (s1==s2-1 || s1==s2)) printf("%d
",s2+2);
16         if ((!s1) || s1<=s2-2) printf("%d
",s2+1);
17         if (s1>s2) printf("%d
",s1+2);
18     }
19     return 0;
20 }
Intersection

1005 Chess:f[i][j]表示1~i中放了j个传送器,且保证1能到i的方案数。枚举上一个没放传送器的位置,两地之间的位置的传送器传送到哪没有限制。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
 5 typedef long long ll;
 6 using namespace std;
 7 
 8 const int N=1010,mod=1e9+7;
 9 int T,n,m,f[N][N];
10 
11 int main(){
12     for (scanf("%d",&T); T--; ){
13         scanf("%d%d",&n,&m); memset(f,0,sizeof(f)); f[1][0]=1;
14         rep(i,1,n) rep(j,0,min(m,i-1)){
15             int t=1;
16             rep(k,1,11) f[i+k][j+k-1]=(f[i+k][j+k-1]+1ll*f[i][j]*t)%mod,t=1ll*t*(i+k-1)%mod;
17         }
18         printf("%lld
",f[n][m]?f[n][m]:-1ll);
19     }
20     return 0;
21 }
Chess

1006 Ant:https://blog.csdn.net/tomjobs/article/details/107684591

 1 #include<cstdio>
 2 #include<algorithm>
 3 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
 4 #define For(i,x) for (int i=h[x],k; i; i=nxt[i])
 5 typedef long long ll;
 6 using namespace std;
 7 
 8 const int N=200010,mod=1e9+7;
 9 int T,n,m,cnt,x,y,h[N],to[N],nxt[N],f1[N],f2[N],sz[N];
10 
11 void add(int u,int v){ to[++cnt]=v; nxt[cnt]=h[u]; h[u]=cnt; }
12 
13 int ksm(int a,int b){
14     int res=1;
15     for (; b; a=1ll*a*a%mod,b>>=1)
16         if (b & 1) res=1ll*res*a%mod;
17     return res;
18 }
19 
20 void dfs(int x,int fa){
21     if (x==m){ f1[x]=1; return; }
22     For(i,x) if ((k=to[i])!=fa){
23         dfs(k,x);
24         if (f1[k]){
25             f1[x]=1ll*f1[k]*ksm(sz[x],mod-2)%mod;
26             f2[x]=1ll*f2[k]*ksm(sz[x],mod-2)%mod;
27             f2[x]=(f2[x]+1ll*f1[x]*ksm(sz[x]-1,mod-2)%mod*(sz[x]-1-(x!=1)))%mod;
28         }
29     }
30 }
31 
32 int main(){
33     for (scanf("%d",&T); T--; ){
34         scanf("%d%d",&n,&m); cnt=0;
35         rep(i,1,n) h[i]=f1[i]=f2[i]=sz[i]=0;
36         rep(i,2,n) scanf("%d%d",&x,&y),add(x,y),add(y,x),sz[x]++,sz[y]++;
37         dfs(1,0); printf("%d
",(f1[1]+f2[1])%mod);
38     }
39     return 0;
40 }
Ant
原文地址:https://www.cnblogs.com/HocRiser/p/13405966.html