整数の区切り

4417 ワード

整数分割問題は多くの人がやったと信じています。
正の整数nを一連の正の整数の和として表し、
n=n 1+n 2+,,,,,,,+n k(そのうちn 1>=n 2>=…>=nk==1,k>1)
例えば、正の整数6は、次の11種類の異なる区分があり、
6=1+1+1+1+1 6=1+1+1+1+2+6=1+1+1+1+3 6=1+1+2+2 6=1+1+4=1+4=1+2+3 6=1+5=2+2+6=2+6=2+6=2+6=2+4=3+6=6
この問題はネットで大きな問題の解き方を探しています。何を遡ってもいいですか?ダイナミック企画などは全部解けます。昨日の夜、突然新しい問題解決の考えが浮かびました。
この問題の厄介な点は、問題を解く過程で繰り返されやすいことですが、次のようにすれば、重複する現象が起こらないということです。
正の整数Nを分割すると、次のような区分がある。
N=1+1+….+1
N=1+1+…+2
……
N=1+(N-1)
N=N
次にN+1(ここでN+1の代わりにMを使用する)を分割すると、N区分の全ての場合の前に1すなわち
M=1+1+1+….+1
M=1+1+1+…+2
……
M=1+N
追加した後に新しい表現ごとに次のように操作します。
ステップ1.表式の個数が2つ以下の場合(例えば、3=1+2式の個数は2つ)、この表式は処理されず、次の表式を判断します。そうでなければ、ステップ2を実行します。
ステップ2.表式の数が2より大きい場合、表式の前の2つの数値を合計します。例えば、5=1+2+3の場合、前の2つの数は1と2です。
元の表式のように、M=x 1+x 2+x 3+....xn
新しい表現はM=(x 1+x 2)+x 2+x 3...+n
7=2+2+3と、前の二つの数字の和は4で、第3の数字より大きい場合。処理を行わずにステップ1に進み、次の式を判定します。
すべての表式(前の数値の表式に1を加えた表式だけを含む。このプロセスで生成された新しい表式を含まない。)が上記の手順を実行した後、結果は1つだけ足りなくなりました。つまり、自分が自分に等しい場合、この状況を追加すればいいです。
話がよく分かりませんので、実際のものを注文しましょう。
5の区分のように、
5=1+1+1+1 5=1+1+1+1+2=1+1+3 5=1+2+2=5=1+4=2+5=2+3=5
6の分割を求めると、まず第1ステップ、5の各表式の前に1を加えると、次のようになります。
6=1+1+1+1+1 6=1+1+1+2+6=1+1+1+1+3=1+1+2+2 6=1+2+2=6=1+1+4=1+2+3=1+5
次に、各表現について、先に述べたステップ1とステップ2を順次実行する。
1.式について:6=1+1+1+1、ステップ1を満たし、ステップ2を実行します。前の2つの数の加算1+1=2は第3の数の1より大きいので、処理を行わずに、式2を判断し続けます。
2.式について: 6=1+1+1+1+2,6=1+1+1+3も同じです。次の表式を続けます。
3.式について: 6=1+1+2+2、前の2つの合計:1+1=2は3番目の数に等しいので、条件を満たして、新しい有効表現を生成します。6=2+2+2、次の表式を続けます。
4.式について: 6=1+1+4、 6=1+2+3と同じように、新しい表現を生成できます。6=2+4,6=3+3
5.式について: 6=1+5はステップ1の条件を満たしていません。
6.すべての表現が遍歴され、終了し、自身が自身に等しい場合、すなわち:6=6
最終的な結果は:
6=1+1+1+1+1 6=1+1+1+1+2+6=1+1+1+1+3 6=1+1+2+2 6=1+1+4=1+4=1+2+3 6=1+5=2+2+6=2+6=2+6=2+6=2+4=3+6=6
やっと書き終わりました。実は簡単な構想ですが、はっきり言えば面倒くさいです。このような考え方によって、コードは書けます。でも、コードもあまりよく書けません。私はここで一番分かりやすいコードで上記の機能を完成しました。
import java.util.ArrayList;
import java.util.List;

public class IntegerSplit {
	private List<int[]> result = new ArrayList<int[]>();
	public void split(int m) {
		//   

		result.add(new int[]{1,1});
		result.add(new int[]{2});
		if (m == 1) {
			System.out.println("1=1");
			System.out.println("   :1 ");
			return ;
		} else {
			for (int i = 3; i <= m; i++) {
				int size=result.size();
				for(int j=0;j<size;j++){
					int[] ca=result.get(j);
					int[] newca=new int[ca.length+1];			
					newca[0]=1;
					System.arraycopy(ca, 0, newca, 1, ca.length);
					ca=null;
					ca=newca;
					result.set(j, ca);
					int[] cs=merger(ca);
					if(cs!=null){
						result.add(cs.clone());
					}
				}
				result.add(new int[]{i});
				
			}
		}
		//    
		for(int[] ca:result){
			System.out.print(m+"=");
			for(int p=0;p<ca.length-1;p++){
				System.out.print(ca[p]+"+");
			}
			System.out.print(ca[ca.length-1]);
			System.out.println();
		}
		System.out.println("   :"+result.size()+" ");
		
	}
	//  
	public int[] merger(int[] ca) {
		if (ca.length <= 2)
			return null;
		if (ca[0] + ca[1] <= ca[2]) {
			int[] rca = new int[ca.length - 1];
			rca[0] = ca[0] + ca[1] ;
			System.arraycopy(ca, 2, rca, 1, ca.length - 2);
			return rca;
		}
		return null;
	}
	public static void main(String[] args) {
		new IntegerSplit().split(10);
	}
}
出力:
10=1+1+1+1+1+1+1+1+1+1
10=1+1+1+1+1+1+1+1+2
10=1+1+1+1+1+1+1+3
10=1+1+1+1+1+1+2+2
10=1+1+1+1+1+1+4
10=1+1+1+1+1+2+3
10=1+1+1+1+1+5
10=1+1+1+1+2+2+2
10=1+1+1+1+2+4
10=1+1+1+1+3+3
10=1+1+1+1+6
10=1+1+1+2+2+3
10=1+1+1+2+5
10=1+1+1+3+4
10=1+1+1+7
10=1+1+2+2+2+2
10=1+1+2+2+4
10=1+1+2+3+3
10=1+1+2+6
10=1+1+3+5
10=1+1+4+4
10=1+1+8
10=1+2+2+2+3
10=1+2+2+5
10=1+2+3+4
10=1+2+7
10=1+3+3+3
10=1+3+6
10=1+4+5
10=1+9
10=2+2+2+2+2
10=2+2+2+4
10=2+2+3+3
10=2+2+6
10=2+3+5
10=2+4+4
10=2+8
10=3+3+4
10=3+7
10=4+6
10=5+5
10=10
   :42 
また、複数のセグメントを追加して、全体を区分するだけで、プロセスのコードを求めません。
public class ZSHF {
	public static int q(int n,int m){
		if(n<1||m<1)return 0;
		if(n==1||m==1)return 1;
		if(n<m)return q(n,n);
		if(n==m)return q(n,m-1)+1;
		return q(n,m-1)+q(n-m,m);
	}
	public static void main(String[] args) {
		int number=10;
		int result=q(number,number);
		System.out.println("   "+number+"      :"+result+" ");
	
	}
}
出力結果:
   10      :42