1. 程式人生 > >P5305 金坷垃

P5305 金坷垃

  一道推斷題(自己編的型別)。

  其實我們做過一些題後發現,有的時候不能模擬,如果我們在螢幕之外想出了這道題的實質,就可以用很簡單的程式碼寫出一道看似很複雜的題(很重要!!!)。

  就以這道題為例吶:

  看似沒什麼能頭緒,其實思考後就能明白就是一個快速冪(要不是資料範圍快速冪都不是):

  (orz)由於感覺洛谷題解很好,就直接拿過來了:

做法1

倒推1(可以這樣矇蔽你自己)

  想要最後得到1,那麼必然存在一個數ii,使得ii減去它的一個因數得到1,那麼滿足條件的只有2了,同理可推得只有4滿足,又因為不能重複跳相同的高度,所以就有了1、2、4、8、16向上不斷加的過程。

做法2

 倒推2(正解)

  我們可以肯定2的次方必然滿足要求(一遍一遍減去一半就行),不好驗證的就是剩下的數。

  對於任意一個2的次方,它只是1、2、4、8...的倍數。也就是說,它不是任何一個非2方數的倍數,那麼它加上這個非2方數後,也不是這個數的倍數。

  根據題中規則,對於一個深度,只能跳它的因數的深度,且用過的深度不能再用,那麼對於任意一個 2方數+非2方數,它一定不是這個非2方數的倍數,也就不能通過減掉這個非2方數來達到2的次方的狀態。

  同理,對於一個2方數+另一個2方數(2個數不等),你減一個非2方數肯定達不到2的次方的狀態,轉入上一段所描述的狀態。

  然後這個兩個數的和一定是其中較小2方數的倍數(不解釋),那麼你需要減去這個較小數以達到2的次方的狀態。

  如果你減去了這個較小2方數(重點來了!),那麼你在這個大的2方數不斷減成1的過程中一定需要再減一遍這個較小的2方數!

  用8+4舉例,為12。已經知道減3、6都不會到達1(看第3段),減去2又不是2方數(10),所以減4。但8往下減小會用到一次4!所以一個2方數+另一個2方數的情況也無法滿足。

  2方數+另一個2方數 和 2方數+非2方數已經表示了除2方數以外的所有數,這兩種情況都是不行的,所以只有2的次方滿足要求。

  最後k<=1e18,記得用快速冪。

  奉上冗長無比的程式碼:

#include<cstdio>
using namespace std;
#define int long long const int mod=123456789; int poww(int a,int b) { int ans=1,base=a; while(b) { if(b&1) ans=ans*base%mod; base=base*base%mod; b>>=1; } return ans; } main() { int n,k; scanf("%lld",&k); int p=poww(2,k-1); printf("%lld",p%mod); return 0; }