洛谷P2150 壽司晚宴

2021-07-28 14:19:03 字數 1964 閱讀 1059

考慮暴力,當n≤

30 時,素數有2 3 5 7 11 13 17 19 23 29,一共10個,狀壓dp可行,f[i][j]表示每個人選數的狀態,然後暴力轉移就好了,複雜度o(

22n)

。然後我就想不出來了……

有乙個常用到的性質就是,對於任何乙個數字

x ,其大於x√

的約數只能有乙個或者沒有,利用這個性質,可以做這道題。

⌊500−−

−√⌋=

22 ,而小於等於22的最大的素數是19,從1到19一共只有8個素數。

可以只壓這8個素數,f[

i][j

] 表示第乙個人的選數狀態為i,第二個人為j的方案數。 將[

2,500]

的所有數分解質因數,大於19的素數最多有乙個,記下來,記作gp[i](giant prime),小素數們壓進二進位制數,記作tp[i](tiny primes)。

接下來是轉移。

對於gp相等的數,我們劃分到一組裡去單獨dp,因為這一組中只能讓乙個人選數,乙個人選了另乙個人就不能再這組裡選了。

對於乙個組,其giant prime是相同的,令g[

i][j

] 表示已經考慮了組中的所有數和前面做完的組的所有數,強制讓第乙個人選擇這個組中的數(乙個數不選的情況也納入考慮),第二個人不能選,這樣的方案數。

初始狀態g[

i][j

]=f[

i][j

] 那麼我們每次加入組中的乙個數

x ,令k=

tp[x

],轉移就是g[

ibit

ork]

[j]+

=g[i

][j]

(當ib

itan

dk==0

),注意迴圈順序要倒序。

做完一組之後,要將

g 和

f陣列合併,f[

i][j

]=g[

i][j

]+g[

j][i

]−f[

i][j

] ,減去f[

i][j

] 是因為兩個人都啥也不選的情況重複了。

這樣有bug,沒有大素數的那一組不能這樣轉移,這樣轉移方案數會變少,因為這一組中只要兩個人不選相同的數字就行,和前面不一樣。

這時直接f[

ibit

ork]

+=f[

i][j

] ,f[

i][j

bito

rk]+

=f[i

][j]

答案就是所有狀態加起來。

//狀壓dp 

#include

#include

#define maxn 1000

#define ll long long

using namespace std;

ll n, p, f[maxn][maxn], g[maxn][maxn], tp[maxn], hp[maxn], mark[maxn], prime[maxn],

num[maxn], h[maxn][maxn];

bool cmp(ll a, ll b)

}for(i=2;i<=n;i++)

for(i=2;i<=n;i++)num[i]=i;

sort(num+2,num+n+1,cmp);

}void dp()

}for(i=0;i<256;i++)for(j=0;j<256;j++)f[i][j]=(g[i][j]+g[j][i]-f[i][j])%p;

}else}}

}for(i=0;i<256;i++)for(j=0;j<256;j++)ans=(ans+f[i][j])%p;

printf("%lld",((ans%p)+p)%p);

}int main()

NOI2015 洛谷P2150 壽司晚宴

為了慶祝noi的成功開幕,主辦方為大家準備了一場壽司晚宴。小g和小w作為參加noi的選手,也被邀請參加了壽司晚宴。在晚宴上,主辦方為大家提供了n 1種不同的壽司,編號1,2,3,n 1,其中第種壽司的美味度為i 1 即壽司的美味度為從2到n 現在小g和小w希望每人選一些壽司種類來品嚐,他們規定一種品...

p2150 NOI2015 壽司晚宴

傳送門 分析 我們發現對於大於 sqrt n 的數每個數最多只會包含乙個 所以我們把每個數按照大質數的大小從小到大排序 我們知道對於一種大質數只能被同乙個人取 所以f1表示被a取,f2表示被b取 最終答案就是這兩個的答案減去啥都不去的答案 因為啥都不去會被重覆記錄兩次 對於小質數則直接狀壓轉移即可 ...

洛谷P2172 bzoj 2150 部落戰爭

lanzerb的部落在a國的上部,他們不滿天寒地凍的環境,於是準備向a國的下部征戰來獲得更大的領土。a國是乙個m n的矩陣,其中某些地方是城鎮,某些地方是高山深澗無人居住。lanzerb把自己的部落分成若干支軍隊,他們約定 每支軍隊可以從任意乙個城鎮出發,並只能從上往向下征戰,不能回頭。途中只能經過...