标签:codeforce names 步骤 排列 ret long using div base
Virtual participation
观察发现任何排列均满足题意。
#include<bits/stdc++.h>
using namespace std;
int N;
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
int T;cin>>T;
while(T--){
cin>>N;
for(int i=1;i<=N;++i)
printf("%d ",i);
puts("");
}
return 0;
}
由于要求从任意位置都能走到右下角,只要让最后一行均为“R”,最后一列均为“D”即可。可以证明这是最优解。
#include<bits/stdc++.h>
using namespace std;
int N,M,ans;
char A[110][110];
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
int T;cin>>T;
while(T--){
ans=0;
cin>>N>>M;
for(int i=1;i<=N;++i)
cin>>A[i]+1;
for(int i=1;i<N;++i)
if(A[i][M]!=‘D‘)
++ans;
for(int j=1;j<M;++j)
if(A[N][j]!=‘R‘)
++ans;
printf("%d\n",ans);
}
return 0;
}
组合数学。
观察发现,只有最大数的左侧升序,右侧降序的排列符合题意。
#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
int N,fac[1000010],ifac[1000010];
long long ans;
int C(int n,int m){
if(n<m)return 0;
return 1ll*fac[n]*ifac[m]%mod*ifac[n-m]%mod;
}
int qpow(int base,int b){
int res=1;
while(b){
if(b&1)res=1ll*res*base%mod;
base=1ll*base*base%mod;
b>>=1;
}
return res;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cin>>N;
fac[0]=1;
for(int i=1;i<=N;++i)
fac[i]=1ll*fac[i-1]*i%mod;
ifac[N]=qpow(fac[N],mod-2);
for(int i=N;i>=1;--i)
ifac[i-1]=1ll*ifac[i]*i%mod;
ans=fac[N];
for(int i=1;i<=N;++i)
ans=(ans-C(N-1,i-1)+mod)%mod;
printf("%lld\n",ans);
return 0;
}
状压DP。
当 \(N\ge 4\) 且 \(M\ge 4\) 时,不存在解。所以行/列不超过3,且只需要考虑 \(2\times 2\) 的子矩阵即可。显然可以状压DP。
记 \(f(i,S)\) 表示“做到第 \(i\) 行(列),当前行(列)的01序列为 \(S\) ”的最少步骤数。
#include<bits/stdc++.h>
using namespace std;
int N,M,A[1000010],B[5],ans;
int F[1000010][10];
char str[1000010];
int getPos(int x,int y){
return x*M+y;
}
int isRight(int k1,int k2,int x){
memset(B,0,sizeof(B));
for(int i=0;i<x;++i,k1>>=1,k2>>=1)
B[i]=(k1&1)+(k2&1);
for(int i=1;i<x;++i)
if((B[i-1]+B[i])%2==0)
return 0;
return 1;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cin>>N>>M;ans=1e6;
for(int i=0;i<N;++i){
cin>>str;
for(int j=0;j<M;++j)
A[getPos(i,j)]=str[j]-‘0‘;
}
if(N>=4&&M>=4)puts("-1");
else{
int tmp;
if(N<2||M<2)puts("0");
else if(N<4){
for(int j=0;j<M;++j)
for(int k=0;k<(1<<N);++k)
F[j][k]=1e6;
for(int k=0;k<(1<<N);++k){
F[0][k]=0;
for(int i=0;i<N;++i)
F[0][k]+=(A[getPos(i,0)]!=((k>>i)&1));
}
for(int j=1;j<M;++j)
for(int k1=0;k1<(1<<N);++k1)
for(int k2=0;k2<(1<<N);++k2)
if(isRight(k1,k2,N)){
tmp=0;
for(int i=0;i<N;++i)
tmp+=(A[getPos(i,j)]!=((k2>>i)&1));
F[j][k2]=min(F[j][k2],F[j-1][k1]+tmp);
}
for(int k=0;k<(1<<N);++k)
ans=min(ans,F[M-1][k]);
printf("%d\n",ans);
}
else if(M<4){
for(int i=0;i<N;++i)
for(int k=0;k<(1<<M);++k)
F[i][k]=1e6;
for(int k=0;k<(1<<M);++k){
F[0][k]=0;
for(int j=0;j<M;++j)
F[0][k]+=(A[getPos(0,j)]!=((k>>j)&1));
}
for(int i=1;i<N;++i)
for(int k1=0;k1<(1<<M);++k1)
for(int k2=0;k2<(1<<M);++k2)
if(isRight(k1,k2,M)){
tmp=0;
for(int j=0;j<M;++j)
tmp+=(A[getPos(i,j)]!=((k2>>j)&1));
F[i][k2]=min(F[i][k2],F[i-1][k1]+tmp);
}
for(int k=0;k<(1<<M);++k)
ans=min(ans,F[N-1][k]);
printf("%d\n",ans);
}
}
return 0;
}
整体做的还不错。
Codeforces Round #663 (Div. 2)训练小结
标签:codeforce names 步骤 排列 ret long using div base
原文地址:https://www.cnblogs.com/dayu2001/p/13780739.html