B - Charm Bracelet
01背包,不知道为什么没过
C - Sliding Window
数据结构,单调队列,线段树
try1:区间dp,这和枚举几乎无差
#include<iostream>
using namespace std;
void solu(){
da[i][i]=a[i];
for(int len=1;len<=maxlen;len++){
for(int i=1;i+len-1<=n;i++){
int j=i+len-1;
for(int k=i;k<=j;k++){
da[i][j]=max(da[i][j],max(da[i][k],da[k+1][j]));
}
}
}
}
又尝试了一遍,分析确实枚举->dp复杂度降低,complite error
开不到这么大的数组
#include<iostream>
#define ll long long
using namespace std;
#define INF 0x3f3f3f3f
ll n,chuangz;
ll dp1[1000000][1000000];
ll dp2[1000000][1000000];
void solu(){
//n^2->nlogn
for(ll len=2;len<=chuangz;len++)
for(ll i=1;i+len-1<=n;i++){
ll j=i+len-1;
for(ll k=i;k<=j-1;k++){
dp1[i][j]=min(dp1[i][j],min(dp1[i][k],dp1[k+1][j]));
dp2[i][j]=max(dp2[i][j],max(dp2[i][k],dp2[k+1][j]));
}
}
cout<<endl;
for(ll i=chuangz;i<=n;i++){
cout<<dp1[i-chuangz+1][i];
if(i!=n)cout<<" ";
}
cout<<endl;
for(ll i=chuangz;i<=n;i++){
cout<<dp2[i-chuangz+1][i];
if(i!=n)cout<<" ";
}
}
int main(){
cin>>n>>chuangz;
for(ll i=1;i<=n;i++)
for(ll j=i+1;j<=n;j++){
dp1[i][j]=INF;dp2[i][j]=-INF;
}
for(ll i=1;i<=n;i++){cin>>dp1[i][i];dp2[i][i]=dp1[i][i];}
solu();
}
D - 摆花
E - 飞扬的小鸟
状压dp,写了一半,思路简单,看出即使蹭天花板,最后不能过关的答案也不变
但有没有管子写起来好几种情况,也可以写,不值,算了
F - 消防局的设立
树形dp
G - 随机数生成器
期望dp
H - 互不侵犯
#include<iostream>
#define ll long long
using namespace std;
ll n,s;
ll maxn;
ll dp[10][1025][101];
ll num[1025];
void solu(){
for(ll j=0;j<maxn;j++)
dp[1][j][num[j]]=1;
for(ll i=2;i<=n;i++){
for(ll j=0;j<maxn;j++){
if(j&(j<<1))continue;
for(ll k=0;k<maxn;k++){
if(k&(k<<1))continue;
if((k&j)||(k&(j<<1))||(j&(k<<1)))continue;
for(ll cnt=num[j];cnt<=s;cnt++)
dp[i][j][cnt]+=dp[i-1][k][cnt-num[j]];
//这里空间太多,没有滚动,正序也对
}
}
}
ll ans=0;
for(ll j=0;j<maxn;j++){
ans+=dp[n][j][s];
}
cout<<ans;
}
ll get_sum(ll x){
ll sum=0;
while(x){
sum+=(x&1);
x>>=1;
}
return sum;
}
int main(){
cin>>n>>s;
maxn=1<<n;
for(ll i=0;i<maxn;i++){
num[i]=get_sum(i);
}
solu();
}
I - Round Numbers
数位dp