1. 程式人生 > >藍橋杯往屆試題:帶分數(全排列、java)

藍橋杯往屆試題:帶分數(全排列、java)

問題描述

100 可以表示為帶分數的形式:100 = 3 + 69258 / 714。

還可以表示為:100 = 82 + 3546 / 197。

注意特徵:帶分數中,數字1~9分別出現且只出現一次(不包含0)。

類似這樣的帶分數,100 有 11 種表示法。

輸入格式

從標準輸入讀入一個正整數N (N<1000*1000)

輸出格式

程式輸出該數字用數碼1~9不重複不遺漏地組成帶分數表示的全部種數。

注意:不要求輸出每個表示,只統計有多少表示法!

樣例輸入1100樣例輸出111樣例輸入2105樣例輸出26

題目要求,輸入一個數,將其轉換為一個整數+分數(a+b/c)的形式,且不重複地包含1~9所有數字。

解題思路:

        根據題意可知a,b,c包含了1~9所有數字且不重複,也就是說abc是數字1~9的一種排列。

        所以,我們可以先對數字數list進行全排列,然後再劃分a,b,c。如果這種劃分滿足條件:a+b/c=number,b%c=0,就記錄數+1。

這種解法的關鍵點在於:

        1.求出數字數list的全排列;

        2.劃分數字a,b,c 各自的位數。

求全排列的方法這裡採用遞迴分治法。遞迴函式,函式迴圈查詢陣列,將數字陣列所有數字查找出來,每查找出一個數,就呼叫自己,查找出除了這個數之外陣列的全排列……

數字a,b,c位數的劃分:a的位數i在1和number的長度nlength之間,那麼,b的第一位為s[nlength],c的最後一位為s[8],bc的長度為9-i;因為b/c為整數,所以b的長度至少為bc長度的一半,不然b/c不可能為整數。

        假設數字數list的一種全排列為s[9],a的長度為i,a的值為na,則b的最後一位可以用c的最後一位來求,即(na*s[8])%10,借b的最後一位和c的最後一位可以判斷b和c的位數劃分。

實現程式碼如下:

import java.util.Scanner;

public class Main{
	static int nlength=0;//輸入整數n的長度
	static int n=0;
	static int count =0;//記錄帶分數個數
	static int[] s=new int[] {1,2,3,4,5,6,7,8,9};//定義陣列
	public static void main(String[] args)
	{
		Scanner input=new Scanner(System.in);
		n=input.nextInt();
//		long start=System.currentTimeMillis();
		nlength=(n+"").length();//記錄n的長度
		allrang(0);//陣列s的全排列
		System.out.println(count);
//		long end=System.currentTimeMillis();
//		System.out.println(end-start);
	}
	public static void allrang(int k)
	{
		if(k==s.length-1)//遍歷了一遍陣列s
		{
			process();
			return;
		}
		else
		{
			for(int i=k;i<s.length;i++)//全排列陣列s
			{
				{int temp=s[k];s[k]=s[i];s[i]=temp;}//交換字首,使之產生下一個字首
				allrang(k+1);//繼續全排列
				{int temp=s[k];s[k]=s[i];s[i]=temp;}//將字首交換回來,繼續做上一個字首的排列
			}
		}
	}
	public static void process()
	{
		String str="";
		for(int i=0;i<s.length;i++)str+=s[i];//將陣列s轉換為字串陣列str
		int a,b,c,na,bc,bl;//n=a+b/c
		for(int i=1;i<=nlength;i++)
		{
			a=dev(0, i-1);//取得a的數值
			na=n-a;//取得b/c的數值
			if(na<=0)return;
			bc=9-i;//取得b和c的位數
			bl=(na*s[8])%10;//用c的最後一位,即陣列的最後一位s[8]來取得b的最後一位
			for(int j=i+bc/2-1;j<=7;j++)//b至少佔有bc長度的一半,不然b/c不可能為整數
			{
				if(s[j]==bl)//找到符合的位置,即b的最後一位
				{
					b=dev(i, j);
					c=dev(j+1, 8);
					if(b%c==0&&b/c==na)
					{
						count++;
					}
					break;
				}
			}
		}
	}
	public static int dev(int a,int b)
	{
		int ans=0;
		for(int i=a;i<=b;i++)
		{
			ans+=s[i];
			ans*=10;
		}
		return ans/10;
	}
}