[cf1463F]Max Correct Set

记$l=a+b,P_{i}$表示$i$是否被选入$S$,则有以下结论——

结论1:若$P_{i}=P_{i+l}$且$S_{0}=\{i\mid 1\le i\le l,P_{i}=1\}$合法,则$S$也合法

反证法,若存在$x,y\in S$使得$|x-y|=a$或$b$,不妨假设$x<y$

设$x=l\cdot x_{0}+r_{x},y=l\cdot y_{0}+r_{y}$(其中$1\le r_{x},r_{y}\le l$),显然$y_{0}=x_{0}$或$x_{0}+1$

若为前者,即$r_{y}-r_{x}=a$或$b$;若为后者,即$r_{y}+l-r_{x}=a$或$b$,进而$r_{x}-r_{y}=a$或$b$

由于$P_{i}=P_{i+l}$,因此$a,b\in S_{0}$,进而与$S_{0}$合法矛盾,即得证

结论2:存在一组最优解满足$P_{i}=P_{i+l}$

任取一组最优解$P_{i}$,考虑对其调整:

设$n=l\cdot n_{0}+r_{n}$(其中$0\le r_{n}<l$),进而将其划分为$2l+1$段,长度分别为$r_{n},l-r_{n},r_{n},l-r_{n},...,r_{n}$

记$a_{i}$为第$i$段中1的个数(下标为$[0,2l]$),考虑以第$i$段和第$i+1$段为循环节(其余均改为与其同奇偶段的情况)

反证法,若不存在满足$P_{i}=P_{i+l}$的最优解,即$\begin{cases}\forall 0\le i\le l,(l+1)a_{2i}+l\cdot a_{2i+1}>\sum_{i=0}^{2l}a_{i}\\\forall 1\le i\le l,(l+1)a_{2i-1}+l\cdot a_{2i}> \sum_{i=0}^{2l}a_{i}\end{cases}$

对于$x\equiv 0(mod\ 2)$​,将上式的$i\in [0,\frac{x}{2})$​和下式的$i\in (\frac{x}{2},l]$​求和,即得到
$$
\sum_{i=0}^{2l}(l+[i\equiv 0(mod\ 2)])a_{i}-(l+1)a_{x}>l\sum_{i=0}^{2l}a_{i}\\
(l+1)a_{x}<\sum_{0\le i\le l}a_{2i}
$$
将该式对所有$x=0,2,...,2l$​求和,显然矛盾,即得证

根据上述两个结论,直接状压dp即可(存储前$\max(x,y)$个数是否选入$S$)

时间复杂度为$o(l\cdot 2^{\max(x,y)})$,可以通过

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 22
 4 int n,l,x,y,ans,cnt[N<<2],f[2][1<<N];
 5 int main(){
 6     scanf("%d%d%d",&n,&x,&y),l=x+y;
 7     if (x>y)swap(x,y);
 8     for(int i=1;i<=l;i++)cnt[i]=n/l+(i<=n%l);
 9     f[0][0]=0;
10     for(int i=0,p=1;i<l;i++,p^=1){
11         memset(f[p],0,sizeof(f[p]));
12         for(int j=0;j<(1<<y);j++){
13             int jj=(j<<1)%(1<<y);
14             f[p][jj]=max(f[p][jj],f[p^1][j]);
15             if (((j>>x-1)&1)||((j>>y-1)&1))continue;
16             f[p][jj|1]=max(f[p][jj|1],f[p^1][j]+cnt[i+1]);
17         }
18     }
19     for(int i=0;i<(1<<y);i++)ans=max(ans,f[l&1][i]);
20     printf("%d\n",ans);
21     return 0;
22 }
View Code

 

posted @ 2022-02-22 16:12  PYWBKTDA  阅读(44)  评论(0编辑  收藏  举报