模拟赛的题
这里,模拟赛的题分 \(3\) 类:
-
\(1\),我赛时 AC,但是认为有价值的。
-
\(2\),我赛后独立 AC,认为有价值的。平常,是我脑子比赛时或多或少出了问题的。
-
\(3\),我赛后看题解 AC,认为有价值的。
loj 3513
类别:\(2\)。
重新定义一下「平衡的」子集。设你选了 \(A_1,\cdots ,A_k\) 行,每行选 \(l_{A_i}\sim r_{A_i}\) 列(满足 \(3\))。
-
都有草。
-
\(A_i\) 连续,满足 \([l_{A_{i}},r_{A_i}]∩[l_{A_{i-1}},r_{A_i-1}]\neq \emptyset\)。
-
\(l\) 先减后增,\(r\) 反之。
设 \(dp_{l,r,a,b}\) 表示这行选了 \([l,r]\),\(l,r\) 现在是增还是减。
转移可以用(二维)前缀和优化。
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define de(x) cout<<#x<<"="<<x<<endl
using ll = long long;
const int N = 155;
const ll mod = 1e9+7;
int n;
char c[N][N];
int pf[N][N];
ll dp[N][N][2][2],sum[N][N][2][2];
ll s(int fa,int fb,int x1,int x2,int y1,int y2){
return (mod+sum[x2][y2][fa][fb]-sum[x2][y1-1][fa][fb]-sum[x1-1][y2][fa][fb]+sum[x1-1][y1-1][fa][fb])%mod;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n;
for (int i=1; i<=n; i++){
for (int j=1; j<=n; j++){
cin>>c[i][j];
pf[i][j]=pf[i][j-1]+(c[i][j]=='G');
}
}
ll ans=0;
for (int i=1; i<=n; i++){
memset(sum,0,sizeof sum);
for (int l=1; l<=n; l++){
for (int r=1; r<=n; r++){
for (int fa=0; fa<2; fa++){
for (int fb=0; fb<2; fb++){
sum[l][r][fa][fb]=sum[l-1][r][fa][fb]+sum[l][r-1][fa][fb]-sum[l-1][r-1][fa][fb]+dp[l][r][fa][fb];
sum[l][r][fa][fb]%=mod;
(sum[l][r][fa][fb]+=mod)%=mod;
}
}
}
}
memset(dp,0,sizeof dp);
for (int l=1; l<=n; l++){
for (int r=l; r<=n; r++){
if (pf[i][r]-pf[i][l-1]!=r-l+1){
continue;
}
(dp[l][r][0][0]+=1)%=mod;
(dp[l][r][0][0]+=s(0,0,l,r,l,r))%=mod;
(dp[l][r][0][1]+=s(0,0,l,r,r+1,n))%=mod;
(dp[l][r][0][1]+=s(0,1,l,r,r,n))%=mod;
(dp[l][r][1][0]+=s(0,0,1,l-1,l,r))%=mod;
(dp[l][r][1][0]+=s(1,0,1,l,l,r))%=mod;
(dp[l][r][1][1]+=s(0,1,1,l-1,r,n))%=mod;
(dp[l][r][1][1]+=s(1,0,1,l,r+1,n))%=mod;
(dp[l][r][1][1]+=s(1,1,1,l,r,n))%=mod;
(dp[l][r][1][1]+=s(0,0,1,l-1,r+1,n))%=mod;
(ans+=dp[l][r][0][0]+dp[l][r][0][1]+dp[l][r][1][0]+dp[l][r][1][1])%=mod;
}
}
}
cout<<ans<<endl;
return 0;
}
// don't waste time!!!
loj 2743
类别:\(2\)。简单题啊,赛时没有看。
先把 \(a\) 排序。
设 \(dp_{i,j,len,c}\) 为 \(i\) 个数确定了,\(j\) 个段,\(len\) 长度,\(c\) 个端点确定了(\(0/1/2\))。
转移:
-
新的长度是 \(len+(a_{i+1}-a_i)\times (2j-c)\)。
-
新建一段,单独成段。
-
连接两段。
-
接在另一段上(左右均可)。
-
单独成段,钦定为端点。
-
接在另一段上,钦定为端点。
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define de(x) cout<<#x<<"="<<x<<endl
using ll = long long;
const int N = 1e2+2;
const int L = 1e3+3;
const ll mod = 1e9+7;
ll n,l,a[N];
ll dp[N][N][L][3];
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n>>l;
for (int i=1; i<=n; i++){
cin>>a[i];
}
if (n==1){
cout<<1<<endl;
return 0;
}
sort(a+1,a+1+n);
dp[0][0][0][0]=1;
for (int i=0; i<n; i++){
for (int j=0; j<=i; j++){
for (int k=0; k<=l; k++){
for (int c=0; c<=2; c++){
ll nw=k+(a[i+1]-a[i])*(2*j-c);
if (nw>l){
continue;
}
(dp[i+1][j+1][nw][c]+=dp[i][j][k][c]*(j+1-c))%=mod;
if (j>1){
(dp[i+1][j-1][nw][c]+=dp[i][j][k][c]*(j-1))%=mod;
}
if (j>0){
(dp[i+1][j][nw][c]+=dp[i][j][k][c]*(2*j-c))%=mod;
}
if (c<2){
(dp[i+1][j+1][nw][c+1]+=dp[i][j][k][c]*(2-c))%=mod;
if (j){
(dp[i+1][j][nw][c+1]+=dp[i][j][k][c]*(2-c))%=mod;
}
}
}
}
}
}
ll ans=0;
for (int i=0; i<=l; i++){
(ans+=dp[n][1][i][2])%=mod;
}
cout<<ans<<endl;
return 0;
}
// don't waste time!!!
loj 3576
类别:\(2\)。
\(dp_{l,r,f}\) 代表还有 \(l\) 个小的,\(r\) 个大的的期望 HILO
次数,上一次是 \(f\)(\(f=0\) 表示 LO
,反之亦然)。
每一个数的被选概率是 \(\frac{1}{l+r}\)。
\(dp_{0,l,r}=\displaystyle \frac{\sum_{l'<l}dp_{0,l',k}+\sum_{r'<r}dp_{1,l,r'}}{l+r}\)
\(dp_{1,l,r}=\displaystyle \frac{\sum_{l'<l}dp_{0,l',k}+\sum_{r'<r}dp_{1,l,r'}}{l+r}+\frac{l}{l+r}\)
下一个答案可以从上一个答案得到,因此可以优化为 \(O(N^2)\)。
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define de(x) cout<<#x<<"="<<x<<endl
using ll = long long;
const int N = 5e3+3;
const ll mod = 1e9+7;
ll pw(ll a,ll b){
ll res=1;
a%=mod;
while (b){
if (b&1){
res=res*a%mod;
}
b>>=1;
a=a*a%mod;
}
return res;
}
ll inv(ll x){
return pw(x,mod-2);
}
int n,x;
int dp[N][N][2],s0[N],s1[N],iv[N];
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n>>x;
for (int i=1; i<=n; i++){
iv[i]=inv(i);
}
for (int l=0; l<=x; l++){
for (int r=0; r<=n-x; r++){
dp[l][r][0]=1ll*(s0[l]+s1[r])*iv[l+r]%mod;
dp[l][r][1]=1ll*(s0[l]+s1[r]+l)*iv[l+r]%mod;
(s1[r]+=dp[l][r][0])%=mod;
(s0[l]+=dp[l][r][1])%=mod;
}
}
ll ans=1;
for (ll i=1; i<=n; i++){
(ans*=i)%=mod;
}
cout<<ans*dp[x][n-x][0]%mod<<endl;
return 0;
}
// don't waste time!!!
CF 575A
类别:\(2\)。没打模拟赛。
分段,矩阵快速幂,线段树。简单题。但是挂了很多次。
-
cin 没有 scanf 快。
-
矩阵不要写反。
-
不要忘开 long long!
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define de(x) cout<<#x<<"="<<x<<endl
using ll = long long;
const int N = 2;
const int M = 5e4+4;
ll mod;
struct matrix {
int mat[N][N];
matrix(){
mat[0][0]=mat[0][1]=mat[1][0]=mat[1][1]=0;
}
void init(int f){
memset(mat,0,sizeof mat);
for (int i=0; i<N; i++){
mat[i][i]=f*1;
}
}
matrix operator * (const matrix &a){
matrix res;
res.init(0);
for (int i=0; i<N; i++){
for (int j=0; j<N; j++){
for (int k=0; k<N; k++){
(res.mat[i][j]+=1ll*a.mat[i][k]*mat[k][j]%mod)%=mod;
}
}
}
return res;
}
matrix operator ^ (ll x){
matrix res;
res.init(1);
matrix a;
for (int i=0; i<N; i++){
for (int j=0; j<N; j++){
a.mat[i][j]=mat[i][j];
}
}
while (x){
if (x&1){
res=res*a;
}
a=a*a;
x>>=1;
}
return res;
}
} x[M<<1],tmp[M<<1],a[M<<1];
matrix dat[M<<2];
void build(int k,int l,int r,int p,matrix ad){
if (l==r){
dat[k]=ad;
return;
}
int mid=l+r>>1;
if (p<=mid){
build(k<<1,l,mid,p,ad);
}
else{
build(k<<1|1,mid+1,r,p,ad);
}
dat[k]=(dat[k<<1]*dat[k<<1|1]);
}
ll k,p,n,m;
ll s[M],b[M<<1];
struct Q {
ll p,v,x;
bool operator < (const Q &a) const {
return p<a.p;
}
} op[M<<1];
int main(){
scanf("%lld%lld%lld",&k,&p,&n);
mod=p;
for (int i=0; i<n; i++){
scanf("%lld",&s[i]);
s[i]%=p;
}
s[n]=s[0];
for (int i=1; i<=n; i++){
x[i].mat[0][0]=0;
x[i].mat[0][1]=1;
x[i].mat[1][0]=s[i-1];
x[i].mat[1][1]=s[i];
build(1,1,n,i,x[i]);
tmp[i]=x[i];
}
scanf("%lld",&m);
matrix al=dat[1];
for (int i=1; i<=m; i++){
scanf("%lld%lld",&op[i].p,&op[i].v);
op[i].v%=mod;
op[i+m]=op[i];
op[i+m].p++;
op[i].x=1;
}
m<<=1;
sort(op+1,op+1+m);
while (op[m].p>k){
m--;
}
ll kg=k/n,cur=0;
for (int i=1; i<=m; ){
int j=i;
while (j<m && (op[j+1].p-1)/n==(op[i].p-1)/n){
j++;
}
for (int k=i; k<=j; k++){
int gk=(op[k].p-1)%n+1;
tmp[gk].mat[1][op[k].x]=op[k].v;
build(1,1,n,gk,tmp[gk]);
}
if ((op[j].p-1)/n==kg){
break;
}
a[++cur]=dat[1];
b[cur]=(op[j].p-1)/n;
for (int k=i; k<=j; k++){
int gk=(op[k].p-1)%n+1;
tmp[gk]=x[gk];
build(1,1,n,gk,x[gk]);
}
i=j+1;
}
matrix ans;
ans.init(1);
ll lst=0;
for (int i=1; i<=cur; i++){
ans=ans*(al^(b[i]-lst));
ans=ans*a[i];
lst=b[i]+1;
}
ans=ans*(al^(kg-lst));
for (int i=1; i<=k%n; i++){
ans=ans*tmp[i];
}
printf("%d\n",ans.mat[0][1]);
return 0;
}
// don't waste time!!!
loj 2550
类别:\(1\)。用时 \(3\)h。
评价:打表猜结论!
arc 157f
类别:\(2\)。有两处没有开 long long!
待更!!!