当前位置:首页 » Project Euler » 详细页

Product-sum numbers 题号:88 难度: 40 中英对照

A natural number, N, that can be written as the sum and product of a given set of at least two natural numbers, {a1, a2, ... , ak} is called a product-sum number: N = a1 + a2 + ... + ak = a1 × a2 × ... × ak.

For example, 6 = 1 + 2 + 3 = 1 × 2 × 3.

For a given set of size, k, we shall call the smallest N with this property a minimal product-sum number. The minimal product-sum numbers for sets of size, k = 2, 3, 4, 5, and 6 are as follows.

k=2: 4 = 2 × 2 = 2 + 2
k=3: 6 = 1 × 2 × 3 = 1 + 2 + 3
k=4: 8 = 1 × 1 × 2 × 4 = 1 + 1 + 2 + 4
k=5: 8 = 1 × 1 × 2 × 2 × 2 = 1 + 1 + 2 + 2 + 2
k=6: 12 = 1 × 1 × 1 × 1 × 2 × 6 = 1 + 1 + 1 + 1 + 2 + 6

Hence for 2≤k≤6, the sum of all the minimal product-sum numbers is 4+6+8+12 = 30; note that 8 is only counted once in the sum.

In fact, as the complete set of minimal product-sum numbers for 2≤k≤12 is {4, 6, 8, 12, 15, 16}, the sum is 61.

What is the sum of all the minimal product-sum numbers for 2≤k≤12000?

Solution

利用$n[k]$表示the minimal product-sum number for $k$。 则$n[k]$的下界是$k$,上界是$2k$。前者是显然的,后者可以理解为$2k=2 \times k \times 1 \times ... \times 1$,其中有$k-2$个$1$。 所以对于数$n$而言,其因式分解后的因子个数为$pcnt$,这些因子的和为$psum$,则需要添加$1$的个数为$n-psum$,所以$k=n-psum+pcnt$。 然后暴力枚举即可。

Code


public final class p88 {
    public static void main(String[] args) {
        long start=System.nanoTime();
        String result = run();        
        long end=System.nanoTime();
        System.out.println(result);
        System.out.println( (end-start)/1000000 + "ms" );
    }	
    static public boolean vis[]=new boolean[24444];
    static public int psn[]=new int[12222];
    
    static public String run(){
    	int ans=0;
    	getPSN(1,1,1);
    	for(int k=2;k<=12000;k++){
    		if(vis[psn[k]]==false){
    			vis[psn[k]]=true;
    			ans+=psn[k];
    		}
    	}
    	return Integer.toString(ans);
    }
    static public void getPSN(int n,int psum,int pcnt){
    	//n是当前的数字,psum是其分解的因子之和,pcnt是分解的因子个数
    	int k=n-psum+pcnt;//需要添加1的个数
    	if(k>12000) return;
    	if(psn[k]==0 || psn[k]>n)
    		psn[k]=n;
    	for(int i=2;i*n<=24000;i++)
    		getPSN(i*n,psum+i,pcnt+1);//计算i*n的psn
    }
}
7587457
48ms