1. 程式人生 > >HDOJ 1005 Number Sequence 非48週期法

HDOJ 1005 Number Sequence 非48週期法

Problem DescriptionA number sequence is defined as follows:

f(1) = 1, f(2) = 1, f(n) = (A * f(n - 1) + B * f(n - 2)) mod 7.

Given A, B, and n, you are to calculate the value of f(n).

InputThe input consists of multiple test cases. Each test case contains 3 integers A, B and n on a single line (1 <= A, B <= 1000, 1 <= n <= 100,000,000). Three zeros signal the end of input and this test case is not to be processed.

OutputFor each test case, print the value of f(n) on a single line.

Sample Input1 1 31 2 100 0 0
Sample Output25

網上的版本多數有些問題,最大的問題在於迴圈週期並非48.

這題需要“打草稿”,先求每對a,b出來的數的規律,看一遍輸出估計一下有沒有規律;

然後程式設計找規律,比如重複出現1,1時說明進入了新迴圈;

然後發現有的ab對下不會再出現新的1,1,也就是說第一個元素不參與迴圈週期

——雖然這裡的數對都是(1,0)(2,0)……而題目說不會出現0,但是!7%7=0啦。

此外還有(0,0)對從第三項開始均為0.

整理得到程式如下:

#include<iostream>
using namespace std;
# define LENT 100                      //超過50即可,所謂打草稿的意義

int main() {
	int a, b,c;
		int d[7][7][LENT];            //免得輸出時重複算,乾脆儲存個三維陣列
		int cycle[7][7];              //儲存每對ab得到數列的迴圈週期 
	
		for (a = 0; a < 7; a++) {
			for (b = 0; b < 7; b++) {
				cycle[a][b]=0;                            //用於後續找不符合1,1……的迴圈週期
				d[a][b][1]=1;                             //bug1:忘記做起始資料
				d[a][b][2]=1;				
				for (int i = 3; i < LENT; i++) {           //尋找符合1,1……的迴圈週期
					d[a][b][i] = (a * d[a][b][i-1] + b * d[a][b][i-2]) % 7;
					if (d[a][b][i]==1){
						if(d[a][b][i-1]==1){
						cycle[a][b]=i-2;            //驗證本項、上一項均為1後,確定週期長為i-2
						d[a][b][0]=d[a][b][i-2];    //bug2:當項數恰為週期的倍數時,沒這裡藥丸			
						break;                      
						}
					}
					
				}
				if (0==cycle[a][b]){                    //找不符合1,1……的迴圈週期,用負數標註
					for (int i =4; i < 20; i++) {       //注意要從第四項開始找
						if(d[a][b][i-1]==1)if(d[a][b][i]==d[a][b][3]){
							cycle[a][b]=-(i-3);  		//bug3:算不清週期長度(建議畫個圖)						
							break;
						}											
					}
				}
		        //cout<<a <<" "<<b<<": "<<cycle[a][b]<<endl; //可在這加一句輸出看看每對的週期
			}
			
		}
		
		while(cin>>a>>b>>c){                            //終於開始輸入輸出!前面部分應該寫成函式呼叫,但我不熟
			if (0==c)break;                             //退出條件
			a=a%7;                                      //把ab化成小ab對
			b=b%7;
			if(0>cycle[a][b]){                          //判斷出是不符合1,1……的迴圈週期
				if(0==c);
				else {
					c=c%(-cycle[a][b]);
					if(c<2)c-=cycle[a][b];		 		//bug3:畫圖判斷為何有這句			
				}
			}
			else if(0==cycle[a][b]){                    //0,0對從第三項開始均為0
				if(c>2)c=3;				
			}
			else  c=c%cycle[a][b];                      //正常週期的輸出
			cout<<d[a][b][c]<<endl;
		}
	return 0;

}

三維陣列確實看得人很頭疼,書寫也沒有什麼規範,但我好像沒有找到我能理解的又簡潔又正確的答案了……

還有,這裡看著好好的,部落格裡咋全亂了喲。