日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[BZOJ 2734] 集合选数

發布時間:2024/6/30 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [BZOJ 2734] 集合选数 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Link:

BZOJ 2734 傳送門

Solution:

真是奧妙重重的建模啊.....

我們發現$x,2*x,3*x$這些數太分散了,難以處理

于是我們構建這樣的表格:

?

x ?3x ?9x ?27x....

2x ?6x ?18x ?54x...

4x ?12x ? 36x ?108x...

...? ?.....? ? .....? ? ......

?

將問題轉化為求表格上任意兩點不相鄰的點集數

由于$2^{17}>100000$,因此直接對每一行的信息狀壓就行了

設$dp[i][j]$為到第$i$行且其狀態為$j$時的方案總數,上一層狀態為$k$,判斷!(k&j) && !(j&(j>>1))即可

?

Note:由于一個表格不能包含所有數,因此要建多個表格,結果相乘

Code:

//by NewErA #include <bits/stdc++.h>using namespace std; typedef long long ll; const int MOD=1e9+1;const int MAXN=100005; ll n,dp[50][MAXN],dat[50][50],len[50],last; bool vis[MAXN];ll cal(int x) {dat[1][1]=x;for(int i=1;;i++){if(i>1) dat[i][1]=dat[i-1][1]*2;if(dat[i][1]>n){last=i-1;break;}vis[dat[i][1]]=true;for(int j=2;;j++){dat[i][j]=dat[i][j-1]*3;if(dat[i][j]>n){len[i]=j-1;break;}vis[dat[i][j]]=true;}}for(int i=0;i<=last+1;i++)for(int j=0;j<=(1<<len[i]);j++) dp[i][j]=0;dp[0][0]=1;len[0]=1; //狀壓DPfor(int i=0;i<=last;i++)for(int j=0;j<(1<<len[i]);j++)if(dp[i][j])for(int k=0;k<(1<<len[i+1]);k++)if(!(j&k) && !(k&(k>>1))) dp[i+1][k]=(dp[i+1][k]+dp[i][j])%MOD;return dp[last+1][0]; }int main() {cin >> n;ll res=1;for(int i=1;i<=n;i++)if(!vis[i]) res=res*cal(i)%MOD;cout << res;return 0; }

?

Review:

1、當信息較為分散時,通過構建矩陣等各類方式將相關條件集中處理

?

2、求矩陣中任意兩點不相鄰的點集數(經典問題)

狀壓DP的應用,整體$!(j&k)$和$!k&(k>>1)$判斷的方式還行

?

轉載于:https://www.cnblogs.com/newera/p/9141390.html

總結

以上是生活随笔為你收集整理的[BZOJ 2734] 集合选数的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。