zoukankan      html  css  js  c++  java
  • Project Euler 78:Coin partitions

    Coin partitions

    Let p(n) represent the number of different ways in which n coins can be separated into piles. For example, five coins can separated into piles in exactly seven different ways, so p(5)=7.

    OOOOO
    OOOO O
    OOO OO
    OOO O O
    OO OO O
    OO O O O
    O O O O O

    Find the least value of n for which p(n) is divisible by one million.


    硬币分拆

    记p(n)是将n枚硬币分拆成堆的不同方式数。例如,五枚硬币有7种分拆成堆的不同方式,因此p(5)=7。

    OOOOO
    OOOO O
    OOO OO
    OOO O O
    OO OO O
    OO O O O
    O O O O O

    找出使p(n)能被一百万整除的最小n值。

     

    思路:

    求数的拆分有多少种

    再判断是否能被一百万整除

     

    参考资料:wiki ,PartitionFunctionP

     

    法一:

    image

     

    根据这个等式:

    高能预警:

    1.image  这里是两部分的和

    2.当第一个不满足条件,即:n<k(3k-1)/2 时候,第二个一定不成立

    3.第一个满足条件,第二个可能不满足条件,这里说的条件都是数组下标不能越界

    4.满足条件的都要计算,只有当第一个不满足条件的时候才本次循环

    5.前面的(-1)^(k+1),要乘进去,展开计算,就是计算符合条件的数组

    关键程序:

    for(k=1;k<=n;k++){
                    gk1 = k*(3*k-1)/2;
                    gk2 = gk1+k;
                    if(gk1>n) break;
                        plist.set(n,plist.get(n)+flag*plist.get(n-gk1));
                        if(gk2<=n){
                        plist.set(n,plist.get(n)+flag*plist.get(n-gk2));
                        }
                        plist.set(n,plist.get(n)%limit);                    
                        flag*=-1;
                }

     

    这里由于我只是在上面看到的求解表达式,造成我搞了好久都没有搞出来,没文化正可怕

     

    法二:

    image

    看到这里还没有出问题

     

    image

    看到这里,直接根据上面的表达式求解了,然而这里的k不是从1-n,这里我又理解错了,以为拿来用就好了

     

    上面的方法不行,下面的方法也不行,真是浪费了好多时间的

    下面程序中有一个求k的过程,这里才是真谛啊!!!

    关键程序:

    while(gk<=n){
                    flag = (i%4>1)?-1:1;
                    plist.set(n,plist.get(n)+flag*plist.get(n-gk));
                    plist.set(n,plist.get(n)%limit);
                    i++;
                    int  k= (i%2==0)?i/2+1:-(i/2+1);
                    gk = k*(3*k-1)/2;
                }

    Java程序:

    package Level3;
    
    import java.util.ArrayList;
    
    public class PE078{
        
        void run(){
            int limit = 1000000;
            partitions2(limit);
        }
        void partitions2(int limit){
            ArrayList<Integer> plist = new ArrayList<Integer>();
            plist.add(1);
            int n = 1;
            while(true){
                int gk1 =1;
                int gk2 =2;
                int k=1;
                plist.add(0);// 初始第n
                int flag = 1;
                for(k=1;k<=n;k++){
                    gk1 = k*(3*k-1)/2;
                    gk2 = gk1+k;
                    if(gk1>n) break;
                        plist.set(n,plist.get(n)+flag*plist.get(n-gk1));
                        if(gk2<=n){
                        plist.set(n,plist.get(n)+flag*plist.get(n-gk2));
                        }
                        plist.set(n,plist.get(n)%limit);                    
                        flag*=-1;
                }
                if(plist.get(n)==0)
                    break;
                n++;
            }
            System.out.println(n);
        }
    //    55374
    //    running time=0s784ms
        void partitions1(int limit){
            ArrayList<Integer> plist = new ArrayList<Integer>();
            plist.add(1);
            int n = 1;
            int flag;
            while(true){
                int gk = 1;
                int i = 0;
                plist.add(0);
                while(gk<=n){
                    flag = (i%4>1)?-1:1;
                    plist.set(n,plist.get(n)+flag*plist.get(n-gk));
                    plist.set(n,plist.get(n)%limit);
                    i++;
                    int  k= (i%2==0)?i/2+1:-(i/2+1);
                    gk = k*(3*k-1)/2;
                }
                
                if(plist.get(n)==0)
                    break;
                n++;
            }
            System.out.println(n);
        }
    //    55374
    //    running time=1s155ms
    
        public static void main(String[] args){
            long t0 = System.currentTimeMillis();
            new PE078().run();
            long t1 = System.currentTimeMillis();
            long t = t1 - t0;
            System.out.println("running time="+t/1000+"s"+t%1000+"ms");
            
        }
    }

    法三:

    又给出了求k的一种方式

    关键程序:

    while True:
                gk = k * (3 * k - 1) // 2
                i = n - gk
                if i < 0:
                    break
                pt += (-1) ** (k * k + 1) * p[i]
                k = -1 * k if k > 0 else 1 - k
            p.append(pt)

     

    python程序:

    import time ;
    
    def partitions(limit):
        p = [1, 1, 2]
        n = 2
        while True:
            n += 1
            pt = 0
            i = 0
            k = 1
            while True:
                gk = k * (3 * k - 1) // 2
                i = n - gk
                if i < 0:
                    break
                pt += (-1) ** (k * k + 1) * p[i]
                k = -1 * k if k > 0 else 1 - k
            p.append(pt)
            if pt % limit == 0:
                print "n =", n, "
    "+"partition =", pt
                break
            
    if __name__=='__main__':
        t0 = time.time()
        limit = 1000000
        partitions(limit)
        t1 = time.time()
        print "running time=",(t1-t0),"s"
    
    # n = 55374 
    # running time= 21.3049998283 s

    说明:只有第一种方法是我自己写的,其他是在论坛看到的,自己整理的

  • 相关阅读:
    【poj2478-Farey Sequence】递推求欧拉函数-欧拉函数的几个性质和推论
    【poj1284-Primitive Roots】欧拉函数-奇素数的原根个数
    【hdu2815-Mod Tree】高次同余方程-拓展BadyStepGaintStep
    【poj3243-Clever Y】高次同余方程-拓展BabyStepGiantStep
    数论之高次同余方程(Baby Step Giant Step + 拓展BSGS)
    POJ1094-Sorting It All Out
    POJ-2299 Ultra-QuickSort
    NYOJ542-试制品
    POJ1936-All in All
    POJ3080-Blue Jeans
  • 原文地址:https://www.cnblogs.com/theskulls/p/4852800.html
Copyright © 2011-2022 走看看