1. 程式人生 > >nyoj漢諾塔(一 )解法集合 (主要用快速冪)

nyoj漢諾塔(一 )解法集合 (主要用快速冪)

漢諾塔(一)

時間限制:1000 ms  |  記憶體限制:65535 KB

難度:3

描述

在印度,有這麼一個古老的傳說:在世界中心貝拿勒斯(在印度北部)的聖廟裡,一塊黃銅板上插著三根寶石針。印度教的主神梵天在創造世界的時候,在其中一根針上從下到上地穿好了由大到小的64片金片,這就是所謂的漢諾塔。不論白天黑夜,總有一個僧侶在按照下面的法則移動這些金片:一次只移動一片,不管在哪根針上,小片必須在大片上面。僧侶們預言,當所有的金片都從梵天穿好的那根針上移到另外一根針上時,世界就將在一聲霹靂中消滅,而梵塔、廟宇和眾生也都將同歸於盡。

現在請你計算出起始有m個金片的漢諾塔金片全部移動到另外一個針上時需要移動的最少步數是多少?(由於結果太大,現在只要求你算出結果的十進位制位最後六位)

輸入

第一行是一個整數N表示測試資料的組數(0<N<20)
每組測試資料的第一行是一個整數m,表示起始時金片的個數。(0<m<1000000000)

輸出

輸出把金片起始針上全部移動到另外一個針上需要移動的最少步數的十進位制表示的最後六位。

樣例輸入

2
1
1000

樣例輸出

1
69375
// 快速冪:首先要了解這樣一個公式:a^b mod c=(a mod c)^b mod c(mod為取餘符號即%)(詳細證明請看數論或者離散數學) 
//方法1:用二分法取餘  
#include <stdio.h>
#define mod 1000000
long long pow(long long n)
{
	long long t=1,x=2;
	while( n>0 )
	{
		x %= mod;  
		if(n & 1)
			t = (t * x) % mod;
		x = (x * x) % mod;//先做2的平方,之後2的4次方(2次方的平方)
		n >>= 1;//由於上一步使得n次方縮半 
	}
	return t;
}
int main()
{
	int T;
	scanf("%d", &T);
	while(T--)
	{
		long long m;
		scanf("%lld",&m);
		printf("%lld\n", pow(m) - 1 );
	} 
	return 0;
}
//方法2:用遞迴二分法取餘
#include <stdio.h>
int pm(long long m)
{
	const int p=1000000;
	if(m==1)
		return 2;
	long long t=pm(m>>1);  //m>>1相當於m/2 二分 
	return (t*t%p) * ((m&1?2:1)%p) % p;// m&1 相當於 m%2 如果m是奇數多乘個2,如果是偶數乘以1 (不變) 
}
int main()
{
	int n;
	long long a;
	scanf("%d",&n);
	while(n--)
	{
		scanf("%lld",&a);
		printf("%d\n",pm(a)-1);
	}
}
//思路3:(沒用冪求)
//對於漢諾塔求移動次數公式為f(n+1)=f(n)*2+1;
//此題如果用要求十進位制最後六位,f(n+1)=(f(n)*2+1)%100000;
#include<stdio.h>
int num[100007];
int main()
{
    int N,m,i;
    num[1]=1;  //m=1的情況
    for(i=2;i<100006;i++)
    	num[i]=(2*num[i-1]+1)%1000000;
    scanf("%d",&N);
    while(N--)
    {
        scanf("%d",&m);
        if(m>100005) //這種情況下標對1000000取餘 
        {             
			if(m%100000<6)
        		m=100000+m%10;
          else
           	m%=100000;
        }
         printf("%d\n",num[m]);
     }
     return 0;
 }