2020百度之星
(三)
Chess(经典DP)
http://acm.hdu.edu.cn/showproblem.php?pid=6787
思路:
考虑如果棋盘上连续放置了 11 个传送器,那么这个区域就是无法通过骰子跨过的。而对于一个区域而言,只要上面没有连续 11 个传送器,我们就可以通过控制骰子而成功达到每个可达到的点。由此可以得到一个 dp 方程:设 f[i][j][k] 表示当前考虑到第i个格子,已经用了j个传送器,包括i号位置有连续k个传送器。那么我们的决策就是第i号位置是否放传送器。
代码:
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int mod= 1e9+7; inline int read(){ int k=0,j=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-') j=-1;ch=getchar();} while(ch>='0'&&ch<='9'){k*=10;k+=ch-'0';ch=getchar();} return j*k; } int dp[1005][1005][11]; int main() { int t;scanf("%d",&t); while(t--){ int n=read(),m=read(); memset(dp,0,sizeof(dp)); dp[1][0][0] = 1; for(int i=2;i<=n;i++){ for(int j=0;j<=m;j++){ for(int k=0;k<=10;k++) dp[i][j][0]=(dp[i-1][j][k]+dp[i][j][0])%mod; if(i!=n&&j) for(int k=1;k<=10;k++) dp[i][j][k]=(dp[i][j][k]+1ll*dp[i-1][j-1][k-1]*(i-1)%mod)%mod; } } printf("%d\n",dp[n][m][0]?dp[n][m][0]:-1); } return 0; }
复赛
1001 Battle for Wosneth
用gcd化为最简分数会wa,我也不造为啥。
直接来就可以过了,化简公式,分母幂mod-2,注意mod处理。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const ll mod=998244353; ll quickp(ll a,ll n){ ll ans=1; a%=mod; while(n){ if(n&1) ans=ans*a%mod; a=a*a%mod; n>>=1; } return ans; } int main(){ int t; scanf("%d",&t); while(t--){ ll m,p,q; scanf("%lld%lld%lld",&m,&p,&q); printf("%lld\n",((100*(m*(p-q))%mod+p*q)%mod*quickp(100*p,mod-2)%mod+mod)%mod); } }
1002 Binary Addition
最优操作方法一定是把某个前缀改成全部为1,然后加1,然后直接改不同的位置。
枚举操作的是哪一个前缀。
当前如果是1,则利用一次改变次数,使他成为0。
#include<bits/stdc++.h> using namespace std; #define re register int a[100004],b[100004],dif[100004]; int main(){ int T; scanf("%d",&T); while(T--){ memset(dif,0,sizeof(dif)); int n; scanf("%d",&n); getchar(); for(re int i=1;i<=n;++i){ re char ch=getchar(); a[i]=ch^48; } getchar(); for(re int i=1;i<=n;++i){ re char ch=getchar(); b[i]=ch^48; dif[i]=dif[i-1]; if(a[i]!=b[i]) dif[i]++; } dif[n+1]=dif[n]; a[n+1]=b[n+1]=0; int ans=dif[n],tmp; int num0=0,num1=0; for(int i=1;i<=n+1;++i){ tmp=0; if(a[i]) tmp++; tmp+=num0; tmp++; tmp+=num1; tmp+=dif[n]-dif[i]; if(!b[i]) tmp++; ans=min(tmp,ans); if(!a[i]) num0++; if(b[i]) num1++; } printf("%d\n",ans); } }