cf1303d
題目大意:
有乙個大小為n的揹包,有m個大小為2i(i=0,1,2,3...)的物品,並且每個物品可以分成大小相同的兩份,可以一直分成到大小為1為止,問能否用這些物品把揹包恰好填滿,如果能填滿,輸出拆分物品的最小次數。
解題思路:
通過二進位制的方法,從高位到低位貪心的一位一位處理。
比如樣例一:
10 3
1 32 1
n=10,轉換成二進位制為1010,所以我們看成是1000+10.
三個物品轉換成二進位制分別為:1 100000 1
那麼我們用乙個dp[i]來表示第i位上有多少個1,比如上述的三個物品轉換成dp陣列就是dp[0]=2,dp[5]=1,其餘都為0。
那麼我們只需要從n對應的二進位制的第0位開始與dp進行比較,如果dp[i]上的數量可以滿足n的要求,則直接減去,否則就需要拆分較大的物品,即為向上借位。
具體可以看**及其注釋
1 #include 2 #include 3 #includeview code4 #include 5 #include 6 #include 7 #include 8 #include 9 #include
1011
using
namespace
std;
12#define ll long long
13static
const
int white=0;14
static
const
int gray=1;15
static
const
int black=2;16
static
const
int inf=0x3f3f3f3f
;17 ll pow(ll a,ll b,ll mod)return
sum;}
18int dp[35];//
用來記錄第i位上有多少個1
19void change(int a)//
由於物品的大小都是2的n次方,所以其二進位制一定為1000---的形式
2026
intmain()
2744
if(sum//
全部裝進都裝不滿
4549
int p=0,num=0;50
while(n||dp[p]<0)51
58else
59 dp[p+1]+=dp[p]/2;//
如果低位有的多,可以給高位用
60 n>>1;//
n的最低為處理完成,進一位
61 p++;62}
63 cout
6566
return0;
67 }
Bits Reverse(貪心 位運算)
給定兩個非負整數 x 和 y 規定一種操作,逆序任意三個相鄰的二進位制位。問最少需要多少次操作,能使得 x y 若不能達到,則輸出 1 1 leq t leq 10000 0 leq x,y leq 10 我們先觀察一下這個逆序操作有什麼性質,假設三個相鄰的二進位制位構成乙個三元組 a,b,c 逆序...
CF1010D Mars Over 位運算性質
題目鏈結 資料範圍 略。題解 因為每次只改乙個,改完之後改回去,這個性質很重要。發現有些葉子更改了之後,整體的答案是不變的,因為會出現 他的父親是 操作但是另乙個兒子是 0 這種.故此,我們先算出乙個節點都不更改時,每個節點的值。之後我們通過位運算,對每乙個節點維護乙個 tag 表示這個節點更改會不...
小A的位運算 貪心
題目描述 位運算是乙個非常重要的東西。而小a最近在學習位運算,小a看到了一道很簡單的例題,是說從n個數裡面選出n 1個數要讓它們或起來的值最大,小a想知道這個答案是多少。你可以幫幫他嗎?兩種方法 1.可以用貪心的思路,從大到小依次去更新或值ans,如果或到乙個數沒改變時,說明至少可以不選它,如果一直...