想好久啊+不敢寫啊……但果然人還是應當勇敢自信,只有堅定地去嘗試,才會知道最後的結果。1a真的太開心啦,不過好像我的做法還是比較複雜的樣子……理解起來應該算是比較容易好懂的型別,大家可以參考一下思路~
首先我們先考慮一下簡單的30分演算法:30以內的質數只有十個左右,可以利用狀壓表示出兩個人所選擇的集合,再通過壽司轉移即可。之後的大資料呢?我們發現不能這樣做是因為之後的質數越來越多,狀壓的空間就開不下了。
這時要注意到乙個性質:對於1~n內的每乙個數而言,都可以分解成若干個sqrt(n)的質數。這說明什麼?對於所有的》sqrt(n)的質數而言,我們選擇乙個壽司只可能選擇其中的乙個——換句話說,就是不同的大質數之間的決策是相互獨立的。
於是就有了如下演算法:既然不同的大質數之間不會互相影響,我們就乙個乙個大質數來統計,之後再累加到一起即可。於是我們增加一維的狀態,單獨表示這乙個大質數。0表示兩個集合中均不含有這個大質數因子,1表示第乙個人所選擇的集合中含這個因子,2表示第二個人選擇的集合中含有這個因子。不同的因子之間的轉移將所有1&2的狀態都加入0並清空1&2即可(對於新的質數來說,之前沒有作出過相應的決策,所以是不含有該因子的)。
網上**很短,然而我莫名長……
#include usingnamespace
std;
#define maxn 1000
#define maxt 260
#define int long long
int n, mod, s[maxn], cnst = (1
<< 8) - 1
;int cnt, dp[3
][maxt][maxt], num[maxn], mark[maxn];
int tot, p[maxn], cnp = 8
, ans;
int pri[maxn] = ;
map
map;
intread()
int up(int &x, int
y)void work(inti)}
void dp(intk)
if(k) for(int i = k; i <= n + 1; i +=k) work(i);
else
}}signed main()
if(k != 1 && k != 0
)
else s[++ cnt] =i;
} for(int i = 0; i <= tot; i ++)
dp(p[i]);
for(int i = 0; i <= cnst; i ++)
for(int j = 0; j <= cnst; j ++)
if(i & j) continue
;
else
printf(
"%lld\n
", ans);
return0;
}
題解 NOI2015 壽司晚宴
鏈結 能學好多東西 題意描述 兩個人各從正整數 2 n 500 中取一些數,可以不取 若取出的兩個集合中,任意屬於不同集合的的兩個元素都互質,則方案合法 求合法方案數 首先注意到乙個方案合法的等價條件是 兩個人的質數集合沒有交集 可以想到 f s1 s2 表示兩個人的質數集合為 s1 和 s2 s1...
NOI 2015 壽司晚宴
description 為了慶祝 noi 的成功開幕,主辦方為大家準備了一場壽司晚宴。小 g 和小 w 作為參加 noi 的選手,也被邀請參加了壽司晚宴。在晚宴上,主辦方為大家提供了 n 1 種不同的壽司,編號 1,2,3,n 1,其中第 i 種壽司的美味度為 i 1 即壽司的美味度為從 2 到 n...
NOI 2015 壽司晚宴
4197 noi2015 壽司晚宴 time limit 10 sec memory limit 512 mb submit 813 solved 508 submit status discuss description 為了慶祝 noi 的成功開幕,主辦方為大家準備了一場壽司晚宴。小 g 和小 ...