Lego Blocks
阿新 • • 發佈:2018-12-09
解法真的很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); } } }