【持续更新】【专题】寒假后DP2 + 状压DP1
取数家族
取数1
\(f_{i,0/1}\) 表示取到了第 \(i\) 位,这位取/不取。
#include <bits/stdc++.h>
using namespace std;
#define For(i,x,y,...) for(int i=(x),##__VA_ARGS__;i<=(y);++i)
#define foR(i,x,y,...) for(int i=(x),##__VA_ARGS__;i>=(y);--i)
#define Rep(i,x,y,...) for(int i=(x),##__VA_ARGS__;i<(y);++i)
#define endl '\n'
#define debug(...)
#define debug1(a,i,...) cout<<i<<" "<<a[i]<<endl;
typedef long long ll;
#define fi first
#define se second
#define PII pair<int,int>
#define me(s,x) memset(s,x,sizeof s)
#define pb emplace_back
template<typename T=int>T read(){T x;cin>>x;return x;}
const int mod=998244353;
struct mint{
int x;mint(int x=0):x(x<0?x+mod:x<mod?x:x-mod){}
mint(ll y){y%=mod,x=y<0?y+mod:y;}
mint& operator += (const mint &y){x=x+y.x<mod?x+y.x:x+y.x-mod;return *this;}
mint& operator -= (const mint &y){x=x<y.x?x-y.x+mod:x-y.x;return *this;}
mint& operator *= (const mint &y){x=1ll*x*y.x%mod;return *this;}
friend mint operator + (mint x,const mint &y){return x+y;}
friend mint operator - (mint x,const mint &y){return x-y;}
friend mint operator * (mint x,const mint &y){return x*y;}
};mint Pow(mint x,ll y=mod-2){mint z(1);for(;y;y>>=1,x*=x)if(y&1)z*=x;return z;}
const int N=2e5+10;
int a[N],s[N],f[N][2];
int n;
void MAIN(){
cin>>n;
For(i,1,n){
cin>>a[i];
}
For(i,1,n){
f[i][0]=max(f[i-1][0],f[i-1][1]);
f[i][1]=f[i-1][0]+a[i];
}
cout<<max(f[n][0],f[n][1])<<endl;
}signed main(){
int t=1;while(t--){
MAIN();
}
return 0;
}
取数2
只有取或不取两种情况,直接dp即可。
#include <bits/stdc++.h>
using namespace std;
#define For(i,x,y,...) for(int i=(x),##__VA_ARGS__;i<=(y);++i)
#define foR(i,x,y,...) for(int i=(x),##__VA_ARGS__;i>=(y);--i)
#define Rep(i,x,y,...) for(int i=(x),##__VA_ARGS__;i<(y);++i)
#define endl '\n'
#define debug(...)
#define debug1(a,i,...) cout<<i<<" "<<a[i]<<endl;
typedef long long ll;
#define fi first
#define se second
#define PII pair<int,int>
#define me(s,x) memset(s,x,sizeof s)
#define pb emplace_back
template<typename T=int>T read(){T x;cin>>x;return x;}
const int mod=998244353;
struct mint{
int x;mint(int x=0):x(x<0?x+mod:x<mod?x:x-mod){}
mint(ll y){y%=mod,x=y<0?y+mod:y;}
mint& operator += (const mint &y){x=x+y.x<mod?x+y.x:x+y.x-mod;return *this;}
mint& operator -= (const mint &y){x=x<y.x?x-y.x+mod:x-y.x;return *this;}
mint& operator *= (const mint &y){x=1ll*x*y.x%mod;return *this;}
friend mint operator + (mint x,const mint &y){return x+y;}
friend mint operator - (mint x,const mint &y){return x-y;}
friend mint operator * (mint x,const mint &y){return x*y;}
};mint Pow(mint x,ll y=mod-2){mint z(1);for(;y;y>>=1,x*=x)if(y&1)z*=x;return z;}
const int N=1e6+10;
#define int ll
int a[N],s[N],f[N];
int n;
void MAIN(){
cin>>n;
For(i,1,n){
cin>>a[i];
}
f[1]=0,f[2]=a[1]+a[2];
For(i,3,n){
f[i]=max(f[i-1],f[i-3]+a[i]+a[i-1]);
}
cout<<f[n]<<endl;
}signed main(){
int t=1;while(t--){
MAIN();
}
return 0;
}
取数3
直接dp即可。
就比取数1多了一句话。
#include <bits/stdc++.h>
using namespace std;
#define For(i,x,y,...) for(int i=(x),##__VA_ARGS__;i<=(y);++i)
#define foR(i,x,y,...) for(int i=(x),##__VA_ARGS__;i>=(y);--i)
#define Rep(i,x,y,...) for(int i=(x),##__VA_ARGS__;i<(y);++i)
#define endl '\n'
#define debug(...)
#define debug1(a,i,...) cout<<i<<" "<<a[i]<<endl;
typedef long long ll;
#define fi first
#define se second
#define PII pair<int,int>
#define me(s,x) memset(s,x,sizeof s)
#define pb emplace_back
template<typename T=int>T read(){T x;cin>>x;return x;}
const int mod=998244353;
struct mint{
int x;mint(int x=0):x(x<0?x+mod:x<mod?x:x-mod){}
mint(ll y){y%=mod,x=y<0?y+mod:y;}
mint& operator += (const mint &y){x=x+y.x<mod?x+y.x:x+y.x-mod;return *this;}
mint& operator -= (const mint &y){x=x<y.x?x-y.x+mod:x-y.x;return *this;}
mint& operator *= (const mint &y){x=1ll*x*y.x%mod;return *this;}
friend mint operator + (mint x,const mint &y){return x+y;}
friend mint operator - (mint x,const mint &y){return x-y;}
friend mint operator * (mint x,const mint &y){return x*y;}
};mint Pow(mint x,ll y=mod-2){mint z(1);for(;y;y>>=1,x*=x)if(y&1)z*=x;return z;}
const int N=1e6+10;
ll a[N],s[N],f[N][2];
int n;
void MAIN(){
cin>>n;
For(i,1,n){
cin>>a[i];
}
For(i,1,n){
f[i][0]=max(f[i-1][0],f[i-1][1]);
f[i][1]=f[i-1][0]+a[i];
if(i>1)f[i][1]=max(f[i][1],f[i-2][0]+a[i]+a[i-1]);
}
cout<<max(f[n][0],f[n][1])<<endl;
}signed main(){
int t=1;while(t--){
MAIN();
}
return 0;
}
取数4「ABC162F」
记现在在第 \(i\) 位。
当 \(i\equiv 1\left(mod\space2\right)\) 时,将这个序列分为 \(\frac{i}{2}\) 段,每段 \(2\) 个数,且这些数不相邻,则需要每一段都选出 1 个数。
考虑此位选或不选。
- 若选了第 \(i\) 个数,则第 \(i−1\) 个数就必须不选,答案为 \(f_{i-2}+a_{i}\)。
- 若不选第 \(i\) 个数,则第 \(i−1\) 个数就必须选,以此类推 必须选 \(a_{1},a_{3},a_{5}, \ ... ,a_{i-1}\),所以答案为 \(s_{i-1}\)。
当 \(i\equiv 0\left(mod\space2\right)\) 时,则在这 \(i\) 个数中选择 \(\frac{i-1}{2}\) 个数。
- 若选第 \(i\) 个数,同上。
- 若不选,即在前 \(i-1\) 位选择 \(\frac{i-1}{2}\) 个数,即 \(f_{i-1}\)。
#include <bits/stdc++.h>
using namespace std;
#define For(i,x,y,...) for(int i=(x),##__VA_ARGS__;i<=(y);++i)
#define foR(i,x,y,...) for(int i=(x),##__VA_ARGS__;i>=(y);--i)
#define Rep(i,x,y,...) for(int i=(x),##__VA_ARGS__;i<(y);++i)
#define endl '\n'
#define debug(...)
#define debug1(a,i,...) cout<<i<<" "<<a[i]<<endl;
typedef long long ll;
#define fi first
#define se second
#define PII pair<int,int>
#define me(s,x) memset(s,x,sizeof s)
#define pb emplace_back
template<typename T=int>T read(){T x;cin>>x;return x;}
const int mod=998244353;
struct mint{
int x;mint(int x=0):x(x<0?x+mod:x<mod?x:x-mod){}
mint(ll y){y%=mod,x=y<0?y+mod:y;}
mint& operator += (const mint &y){x=x+y.x<mod?x+y.x:x+y.x-mod;return *this;}
mint& operator -= (const mint &y){x=x<y.x?x-y.x+mod:x-y.x;return *this;}
mint& operator *= (const mint &y){x=1ll*x*y.x%mod;return *this;}
friend mint operator + (mint x,const mint &y){return x+y;}
friend mint operator - (mint x,const mint &y){return x-y;}
friend mint operator * (mint x,const mint &y){return x*y;}
};mint Pow(mint x,ll y=mod-2){mint z(1);for(;y;y>>=1,x*=x)if(y&1)z*=x;return z;}
const int N=2e5+10;
#define int ll
int a[N],s[N],f[N];
int n;
void MAIN(){
cin>>n;
For(i,1,n){
cin>>a[i];
if(i==1) s[1]=a[1];
else if(i&1) s[i]=s[i-2]+a[i];
}
For(i,2,n){
if(i&1){
f[i]=max(f[i-2]+a[i],f[i-1]);
}
else{
f[i]=max(f[i-2]+a[i],s[i-1]);
}
}
cout<<f[n]<<endl;
}signed main(){
int t=1;while(t--){
MAIN();
}
return 0;
}
泰迪熊
直接枚举4种泰迪熊的个数即可。
思路很简单,实现很麻烦/ll。
#include <bits/stdc++.h>
using namespace std;
#define For(i,x,y,...) for(int i=(x),##__VA_ARGS__;i<=(y);++i)
#define foR(i,x,y,...) for(int i=(x),##__VA_ARGS__;i>=(y);--i)
#define Rep(i,x,y,...) for(int i=(x),##__VA_ARGS__;i<(y);++i)
#define endl '\n'
#define debug(...)
#define debug1(a,i,...) cout<<i<<" "<<a[i]<<endl;
typedef long long ll;
#define fi first
#define se second
#define PII pair<int,int>
#define me(s,x) memset(s,x,sizeof s)
#define pb emplace_back
template<typename T=int>T read(){T x;cin>>x;return x;}
const int mod=1e6;
struct mint{
int x;mint(int x=0):x(x<0?x+mod:x<mod?x:x-mod){}
mint(ll y){y%=mod,x=y<0?y+mod:y;}
mint& operator += (const mint &y){x=x+y.x<mod?x+y.x:x+y.x-mod;return *this;}
mint& operator -= (const mint &y){x=x<y.x?x-y.x+mod:x-y.x;return *this;}
mint& operator *= (const mint &y){x=1ll*x*y.x%mod;return *this;}
friend mint operator + (mint x,const mint &y){return x+y;}
friend mint operator - (mint x,const mint &y){return x-y;}
friend mint operator * (mint x,const mint &y){return x*y;}
};mint Pow(mint x,ll y=mod-2){mint z(1);for(;y;y>>=1,x*=x)if(y&1)z*=x;return z;}
const int N=40;
int a1,a2,b1,b2;
int ch[]={0,1,1,2,2},num[]={0,1,2,1,2};
mint f[N][N][N][N][5][5];
void MAIN(){
cin>>a1>>a2>>b1>>b2;
f[0][0][0][0][0][0]=1;
For(i1,0,a1)For(i2,0,a2)For(j1,0,b1)For(j2,0,b2)For(x,0,4)For(y,0,4){
int d=f[i1][i2][j1][j2][x][y].x;
if(d==0) continue;
bool isa=ch[x]==1&&ch[y]==1;
bool isb=ch[x]==2&&ch[y]==2;
bool is1=num[x]==1&&num[y]==1;
bool is2=num[x]==2&&num[y]==2;
if(!isa&&!is1&&i1<a1) f[i1+1][i2][j1][j2][y][1]+=d;
if(!isa&&!is2&&i2<a2) f[i1][i2+1][j1][j2][y][2]+=d;
if(!isb&&!is1&&j1<b1) f[i1][i2][j1+1][j2][y][3]+=d;
if(!isb&&!is2&&j2<b2) f[i1][i2][j1][j2+1][y][4]+=d;
}
mint ans=0;
For(i,0,4)For(j,0,4) ans+=f[a1][a2][b1][b2][i][j];
cout<<ans.x<<endl;
}signed main(){
int t=1;while(t--){
MAIN();
}
return 0;
}
不喜欢非整数
先枚举选数个数 \(p\)。
\(f_{i,j,k}\) 表示前 \(i\) 个数选 \(j\) 个数余数为 \(k\) 的情况数。
转移方程:
\[f_{i+1,j,k}=f_{i+1,j,k}+f_{i,j,k}\\
f_{i+1,j+1,(k+a_{i})mod\space k}=f_{i+1,j+1,(k+a_{i})mod\space k}+f_{i,j,k}
\]
刷表做就行了。
#include <bits/stdc++.h>
using namespace std;
#define For(i,x,y,...) for(int i=(x),##__VA_ARGS__;i<=(y);++i)
#define foR(i,x,y,...) for(int i=(x),##__VA_ARGS__;i>=(y);--i)
#define Rep(i,x,y,...) for(int i=(x),##__VA_ARGS__;i<(y);++i)
#define endl '\n'
#define debug(...)
#define debug1(a,i,...) cout<<i<<" "<<a[i]<<endl;
typedef long long ll;
#define fi first
#define se second
#define PII pair<int,int>
#define me(s,x) memset(s,x,sizeof s)
#define pb emplace_back
template<typename T=int>T read(){T x;cin>>x;return x;}
const int mod=998244353;
struct mint{
int x;mint(int x=0):x(x<0?x+mod:x<mod?x:x-mod){}
mint(ll y){y%=mod,x=y<0?y+mod:y;}
mint& operator += (const mint &y){x=x+y.x<mod?x+y.x:x+y.x-mod;return *this;}
mint& operator -= (const mint &y){x=x<y.x?x-y.x+mod:x-y.x;return *this;}
mint& operator *= (const mint &y){x=1ll*x*y.x%mod;return *this;}
friend mint operator + (mint x,const mint &y){return x+y;}
friend mint operator - (mint x,const mint &y){return x-y;}
friend mint operator * (mint x,const mint &y){return x*y;}
};mint Pow(mint x,ll y=mod-2){mint z(1);for(;y;y>>=1,x*=x)if(y&1)z*=x;return z;}
const int N=105;
int n;
mint f[N][N][N];
mint ans;
int a[N];
void MAIN(){
cin>>n;
For(i,1,n) cin>>a[i];
For(p,1,n){
me(f,0);
f[1][0][0]=1;
For(i,1,n)For(j,0,min(i,p))Rep(k,0,p){
f[i+1][j][k]+=f[i][j][k];
if(j!=p) f[i+1][j+1][(k+a[i])%p]+=f[i][j][k];
}
ans+=f[n+1][p][0];
}
cout<<ans.x<<endl;
}signed main(){
int t=1;while(t--){
MAIN();
}
return 0;
}

浙公网安备 33010602011771号