bzoj 2734 集合選數

2022-04-08 00:40:51 字數 1620 閱讀 1778

written with stackedit.

《集合論與圖論》這門課程有一道作業題,要求同學們求出\(\\)的所有滿足以 下條件的子集:若 \(x\) 在該子集中,則 \(2x\) 和 \(3x\) 不能在該子集中。同學們不喜歡這種具有列舉性 質的題目,於是把它變成了以下問題:對於任意乙個正整數 \(n\leq 100000\),如何求出\(\\) 的滿足上述約束條件的子集的個數(只需輸出對 \(1000000001\) 取模的結果),現在這個問題就 交給你了。

只有一行,其中有乙個正整數 \(n\),\(30\%\)的資料滿足 \(n\leq20\)。

僅包含乙個正整數,表示\(\\)有多少個滿足上述約束條件 的子集。

【樣例解釋】

有\(8\) 個集合滿足要求,分別是\(\emptyset\),\(\\),\(\\),\(\\),\(\\),\(\\),\(\\),\(\\).

\[\begin

1 & 3 & 9 & 27 & ...\\

2 & 6 & 18 & 54 & ...\\

4 & 12 & 36 & 108 & ...\\

8 & 24 & 72 & 216 & ...\\

... & ... & ... & ... & ...\\

\end \quad\]

左上角的數增大時,矩陣沒有填入數字的部分也不斷增大.手動\(memset\).

#includeusing namespace std;

typedef long long lovelive;

inline int read()

while (jp>='0'&&jp<='9')

return out*fh;

}const int p=1e9+1;

inline int add(int a,int b)

inline int mul(int a,int b)

const int maxn=1e5+10;

int n;

int vis[maxn];

int martix[20][20];

int limit[20];//第i行的邊界

int ans=1;

int r,c;

int judge(int st)

return 1;

}vectorg;

void build_martix(int x)

martix[i][1]=p;

vis[p]=1;

for(int j=2;j<20;++j)

martix[i][j]=p;

vis[p]=1;

}} g.clear();

int s=1break;

if(check(i,st))

res=add(res,dfs(k-1,i));

} return res;

}void solve(int x)//以x為左上角構造矩陣的方案數

//memset(f,-1,sizeof f);

ans=mul(ans,dfs(r+1,0));

}int main()

bzoj 2734 集合選數

構造矩陣 1 3 9 27 2 6 18 54 4 12 36 108 每個數是上面的數乘2,左面的數乘3。這樣進行狀壓dp就是相鄰的格仔不能選的方案數。如何判斷乙個二進位制數沒有兩個連續的1?x x 1 0 如果有的數沒有出現過,就以它為左上角元素再構造乙個矩陣。這是怎麼想到的?include i...

BZOJ2734 集合選數

集合論與圖論 這門課程有一道作業題,要求同學們求出的所有滿足以 下條件的子集 若 x 在該子集中,則 2x 和 3x 不能在該子集中。同學們不喜歡這種具有列舉性 質的題目,於是把它變成了以下問題 對於任意乙個正整數 n 100000,如何求出 的滿足上述約束條件的子集的個數 只需輸出對 1,000,...

BZOJ 2734 集合選數(狀態壓縮DP)

題意 給出乙個由1到n的數字組成的集合。定義合法子集為若x在子集中則2x 3x均不能在子集中。求有多少個合法的子集。思路 1 3 9 2 6 18 4 12 36 對於上面的矩陣,我們發現就等價於不選相鄰數字的方案數。因此列舉每個還沒有用到的數字,建立以該數字為左上角的矩陣。接著就是狀態壓縮dp。i...