1. 程式人生 > >Lego Blocks

Lego Blocks

解法真的很impressive,橫著要考慮,豎直的角度也要考慮。

先考慮簡單的情況:沒有第二個限制,每層就是獨立的,對於一層用DP求出n情況下的可能數,然後快速冪得到n層的可能數。

現在加上第二個限制,一個思路就是從隨便放的所有情況減去違反第二個限制的情況數。現在就focus在求違反第二個現在的總數。

很明顯,需要迴圈列舉一下不滿足的列是第幾列,然後該列把M列分成了2部分,2部分不能是隨便放的,這樣會有重複。應該是一邊放不違反第二個限制的,一邊隨便放,這樣可以避免重複計算。假設左邊是不違反第二個限制的,那此時列舉的第幾列,就代表:第一次出現違反限制的列數


mod=10**9+7

f=[1]*(1001)
f[1],f[2],f[3]=1,2,4
for i in range(4,1001):
    f[i]=(f[i-1]+f[i-2]+f[i-3]+f[i-4])%mod

def power(a,b):
    res,base=1,a
    while b:
        if b&1:
            res*=base
            res%=mod
        base*=base
        base%=mod
        b=b//2
    return res
    
def legoBlocks(n, m):
    p=[0]*(m+1)
    for i in range(1,m+1): p[i]=power(f[i],n)
    res=[1]*(m+1)
    for i in range(2,m+1):
        res[i]=p[i]
        for j in range(1,i):
            res[i]-=res[j]*p[i-j]
            res[i]=(res[i]+mod)%mod
    return res[m]


print(legoBlocks(2, 2))
print(legoBlocks(3, 2))
print(legoBlocks(2, 3))
print(legoBlocks(4, 4))
            

Java要注意資料溢位,先求mod,然後再check一遍,因為在Python裡面負數取餘會自動變成整數,比如-5%3=1




import java.io.IOException;
import java.util.Arrays;
import java.util.Scanner;

public class Solution {
    
    public static int mod=1000000007, max=1000;
    public static long[]f;

    /*
     * Complete the legoBlocks function below.
     */
    public static int legoBlocks(int n, int m) {
        /*
         * Write your code here.
         */
        return (int) solve(n,m);
    }
    
    public static long solve(int n, int m) {
        long[] p=new long[m+1];
        for(int i=1;i<=m;i++) p[i]=power(f[i],n);
        long[] res=new long[m+1];
        Arrays.fill(res, 1);
        for(int i=2;i<=m;i++) {
            res[i]=p[i];
            for(int j=1;j<i;j++) {
                res[i]-=res[j]*p[i-j];
                res[i]%=mod;
                res[i]=(res[i]+mod)%mod;
                if(res[i]<0) System.out.println("error");
            }
        }
            
        return res[m];
    }
    
    
    
    public static long power(long a,long b) {
        long res=1,base=a;
        while(b!=0) {
            if((b&1)!=0) {
                res*=base;
                res%=mod;
            }
            base*=base;
            base%=mod;
            b=b/2;
        }
        return res;
    }

    private static final Scanner scanner = new Scanner(System.in);

    public static void main(String[] args) throws IOException {
        
        f=new long[max+1];
        Arrays.fill(f, 1);
        f[2]=2;
        f[3]=4;
        for(int i=4;i<=max;i++) f[i]=(f[i-1]+f[i-2]+f[i-3]+f[i-4])%mod;
        
        
        int t = Integer.parseInt(scanner.nextLine().trim());

        for (int tItr = 0; tItr < t; tItr++) {
            String[] nm = scanner.nextLine().split(" ");

            int n = Integer.parseInt(nm[0].trim());

            int m = Integer.parseInt(nm[1].trim());

            int result = legoBlocks(n, m);
            System.out.println(result);
        }

    }
}