1213D1 - Equalizing by Division (easy version)
n才50,a[i]才2e5,让求至少k个相等的数,那我们就直接枚举i=0-2e5看看变成k个i最小的花费次数就可以了
ll n,k,a[55];
int main(){
scanf("%lld%lld",&n,&k);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
sort(a+1,a+n+1);
ll ans=1e18;
for(int i=0;i<=200005;i++){
ll res=0,cnt=0;
for(int j=1;j<=n;j++){
if(cnt>=k) break;
ll x=a[j],sum=0;
while(x>i){
x/=2;
sum++;
}
if(x==i) res+=sum,cnt++;
}
if(cnt>=k) ans=min(ans,res);
}
printf("%lld\n",ans);
return 0;
}
1364C - Ehab and Prefix MEXs 构造
在这题上浪费了两个半小时,,,自己想的思路都没有过掉,最后想的一个也在第21个样例上T掉了,,,a[i]一定是递增的所以b[i]=a[i-1]是一定不会错的,另外就是要注意a[i]==a[i-1]的时候,一直到a[j]!=a[i],b[j]的值一定是等于a[i]的,相等的那些值就尽量用小数来填,不能用后面出现的数
Ehab and Prefix MEXs_逍遥Fau的博客-CSDN博客
ll n,a[100005],b[100005],vis[100005];
vector<ll>v;
int main(){
scanf("%lld",&n);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]),vis[a[i]]=1;
for(int i=1;i<=100000;i++)
if(!vis[i]) v.push_back(i);
ll ind=0;
for(int i=1;i<=n;i++){
if(a[i]==a[i-1]) b[i]=v[ind++];
else b[i]=a[i-1];
printf("%lld ",b[i]);
}
return 0;
}
Collecting Bugs - POJ 2096 - Virtual Judge (vjudge.net) 概率dp
设dp[i][j]为已经找到i种bug,j个子系统有bug所需要的天数的期望,则可以有dp[i-1][j],dp[i][j],dp[i][j-1],dp[i-1][j-1]四种情况转移下来,发现dp[i][j]是可以通过自身转移的,移项就可以,移完项后发现在i==n&&j==s的情况下分母是0,所以应该倒着枚举,状态就变为设dp[i][j]为还需要找到i种bug,j个子系统有bug所需要的天数的期望,那么初始状态就是dp[n][s]=0,dp[0][0]是答案,这题的难点就在于dp[n][s]要设为初始状态,我一开始以为dp[0][0]也是可以作为初始状态的,但是一直不对,最后发现i==n j==s时也是一样需要移项的,所以避免不了除0的情况,所以只能倒着枚举
ll n,s;
double dp[1005][1005];
int main(){
while(scanf("%lld%lld",&n,&s)!=EOF){
dp[n][s]=0;
for(int i=n;i>=0;i--)
for(int j=s;j>=0;j--){
if(i==n&&j==s) continue;
dp[i][j]=((n-i)*j*dp[i+1][j]+i*(s-j)*dp[i][j+1]+(n-i)*(s-j)*dp[i+1][j+1]+n*s)/(n*s-i*j);
}
printf("%.4f",dp[0][0]);
}
return 0;
}
Scout YYF I - POJ 3744 - Virtual Judge (vjudge.net) 概率dp
设dp[i]为走到第i步是安全的概率,dp[i]=p*dp[i-1]+(1-p)*dp[i-2],1e8太大,所以考虑矩阵快速幂(快速求递推式用的),将路分成多个段根据给出的a[i],算出a[i]--a[i-1]这一段之后将第a[i]步的概率变为0,也就是代码中求下一段之前先把ans.mat[0][0]=0,注意第一段的时候还需要ans.mat[0][0]=1,因为是从第一步开始的,答案就是a[n]-1的概率乘以(1-p)
int mod=1e7+7;
double eps=1e-8;
struct matrix{
double mat[2][2];
matrix operator*(matrix const &b)const{
matrix res;
memset(res.mat,0,sizeof(res.mat));
for(int i=0;i<2;i++)
for(int j=0;j<2;j++)
for(int k=0;k<2;k++)
res.mat[i][j]=(res.mat[i][j]+this->mat[i][k]*b.mat[k][j]);
return res;
}
};
matrix matpow(matrix a,ll b){
matrix res;res.mat[0][0]=res.mat[1][1]=1;
res.mat[0][1]=res.mat[1][0]=0;
while(b){
if(b&1) res=a*res;
a=a*a;
b>>=1;
}
return res;
}
ll n,a[15];
double p;
int main(){
while(scanf("%lld%lf",&n,&p)!=EOF){
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);a[0]=1;
matrix res,ans,b;
b.mat[0][0]=p;b.mat[0][1]=1-p;b.mat[1][0]=1;b.mat[1][1]=0;
sort(a+1,a+n+1);
for(int i=1;i<=n;i++){
ll x=a[i]-a[i-1];
res=matpow(b,x);
//cout<<res.mat[0][0]<<" "<<res.mat[0][1]<<" "<<res.mat[1][0]<<" "<<res.mat[1][1]<<endl;
//cout<<b.mat[0][0]<<" "<<b.mat[0][1]<<" "<<b.mat[1][0]<<" "<<b.mat[1][1]<<endl;
if(i==1){
ans.mat[0][0]=1;
ans.mat[0][1]=ans.mat[1][0]=ans.mat[1][1]=0;
}
else ans.mat[0][0]=0;
ans=res*ans;
// cout<<ans.mat[0][0]<<" "<<ans.mat[1][0]<<" "<<i<<endl;
}
double asw=ans.mat[1][0]*(1-p);
printf("%.7f\n",asw);
}
return 0;
}
One Person Game - ZOJ 3329 - Virtual Judge (vjudge.net) 概率dp
设dp[i]为分数到达i时的期望,大于n的情况太多了,但是我们可以倒着推,这样dp[0]就是答案了,
dp[i]=(dp[i+k]*pk)+dp[0]p0+1,pk为得分为k使得概率,p0在这里为抽到a,b,c的概率,也代表抽到任意一种情况的概率,假设dp[i]=x[i]dp[0]+y[i],则带入上面的方程可以求出x[i]=sum(pkx[i+k])+p0,y[i]=sum(pky[i+k])+p0,答案就是y[0]/(1-x[0])
【原创】概率DP总结 by kuangbin - kuangbin - 博客园 (cnblogs.com)
ll t,n,k1,k2,k3,a,b,c;
double x[505],y[505],p[55];
int main(){
scanf("%lld",&t);
while(t--){
cin>>n>>k1>>k2>>k3>>a>>b>>c;
memset(p,0,sizeof(p));
double p0=1.0/k1/k2/k3;
for(int i=1;i<=k1;i++)
for(int j=1;j<=k2;j++)
for(int k=1;k<=k3;k++)
if(i!=a||j!=b||k!=c) p[i+j+k]+=p0;
memset(x,0,sizeof(x));
memset(y,0,sizeof(y));
for(int i=n;i>=0;i--){
x[i]=p0;y[i]=1;
for(int j=1;j<=k1+k2+k3;j++)
x[i]+=p[j]*x[i+j],y[i]+=p[j]*y[i+j];
}
double ans=y[0]/(1-x[0]);
printf("%.16f\n",ans);
}
return 0;
}