151023的測試總結

第一題

【題目及題號】分裂 superoj950
【題解】
根據均值不等式的推廣可以證明把一個數分得越均勻產生的貢獻越大。
所以就可以枚舉將其分成多少份。
又因爲正向求解比較複雜,所以我們考慮把n分成n個一產生的貢獻減去把多少個1合併在一起減少的貢獻。
最大產生的貢獻爲 n*(n-1)/2;
然後把n分成i份 each = n/i,rest = n%i;
現在相當於從rest個each中分別分一個一出來,減少的貢獻爲rest*(each*(each+1)/2);
然後把i-rest個1分在一起成爲each,減少的貢獻爲(i-rest)(each(each-1)/2);
最後將剩下的貢獻與m相比,如果能找到解則輸出。

第二題

【題目及題號】異或計數 superoj951
【題解】
設a1^a2^……^an=sum
本題要考慮兩個限制:
限制一:異或和最後要相同
限制二:不能大於a[i]
考慮限制二,如果ai當前這位爲1,而我們取了0,那麼意味着它之後的位數無論怎麼取都可以滿足限制二。
所以我們只考慮有一個數沒有取滿的情況。(少掉一種全部取滿ai的情況直接+1就好)
f[i][j][k]表示到第i個數當前異或和爲1是否有一個數已經沒有取滿的情況數。
考慮當前位爲p,
a[i+1]的第p位爲0
這一位只能取0,後面能取的方案數則爲((a[i+1]&(2^(p-1)))+1)
a[i+1]的第p位爲1
這一位可以取0或者1
如果取1,f[i][j][k]+((a[i+1]&(2^(p-1)))+1)轉移到f[i+1][j^1][k];(表示取滿)
如果取0,則表示有一個數沒有取滿,f[i+1][j][1] += f[i][j][k]*(2^(p-1));(表示後面所有數都能亂取)
最後ans = ans + f[n][sum[p]][1]/(2^(p-1));
表示到第n個數當前位異或和與sum相同的方案數,要除以2^(p-1)是因爲
1***|#####
2***|#####
3***|#####
4***|#####
——-00000~11111
取到當前這個數時,後面的位全是儘可能地亂取的,爲了滿足異或和的條件我們需要讓一個數能從00000~11111來保證前面的所有方案都可以合法。
所以讓一個當前位可以爲1的數爲0,並舍掉它可以全部取滿的貢獻。所以除掉2^(p-1)即可。
假設當前位沒有一個數爲1,那麼到最後一位一定是f[][][]=0,不會產生貢獻。

第三題
【題目及題號】brainfuck superoj952
待填坑

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章