整数の区切り
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
やっと書き終わりました。実は簡単な構想ですが、はっきり言えば面倒くさいです。このような考え方によって、コードは書けます。でも、コードもあまりよく書けません。私はここで一番分かりやすいコードで上記の機能を完成しました。
正の整数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