1. 程式人生 > >洛谷p1582倒水(思維好題,數學,2進位制問題,程式碼實現)

洛谷p1582倒水(思維好題,數學,2進位制問題,程式碼實現)

題目連結:https://www.luogu.org/problemnew/show/P1582

 

題目猛一看挺難想,但想通了加的原理和合並的原理後就好說了。

肯定和2進位制是緊密相連的,每個瓶子的水升數一定是2的倍數(因為每次合的都是一樣的且都是2的倍數)

看透了這題後本質就是:將一個整數不斷分解成2進位制的表達形式存起來,再從後往前合併(每次ans加上前後兩數之差就可以相等合併)<m時退出即可!

 

另外一個技巧是:算2的次冪不用每次都算,完全可以打表(很方便還省下不少時間)

 1 #include <iostream>
 2 #include <algorithm>
 3
typedef long long ll; 4 using namespace std; 5 ll b[70]; 6 ll t[70]; 7 ll n,m; 8 9 void bit() 10 { 11 b[0]=1; 12 for(int i=1;i<=62;i++) 13 { 14 b[i]=b[i-1]*2; 15 } 16 } 17 18 void sol() 19 { 20 ll x=n; 21 int k=0,p=0; 22 while(x) 23 { 24 for(int i=0
;i<=70;i++) 25 { 26 if(b[i]>x) 27 { 28 x-=b[i-1]; 29 //cout<<b[i-1]<<' ';//觀察分解數,挺有用. 30 t[++p]=b[i-1]; 31 k++; 32 break; 33 } 34 } 35 } 36 //cout<<endl;
37 38 if(k<=m) 39 { 40 cout<<"0"<<endl; 41 return; 42 } 43 44 ll ans=0; 45 for(int i=p;i>=1;) 46 { 47 ans+=t[i-1]-t[i]; 48 i--; 49 t[i]=t[i]*2; 50 51 k--; 52 if(k<=m) break; 53 } 54 cout<<ans<<endl; 55 } 56 57 int main() 58 { 59 bit(); 60 61 cin>>n>>m; 62 63 sol(); 64 65 return 0; 66 }

 

完。