1. 程式人生 > >2019南昌邀請賽 C. Angry FFF Party 大數矩陣快速冪+分類討論

2019南昌邀請賽 C. Angry FFF Party 大數矩陣快速冪+分類討論

dso aligned 鏈接 res party ini style 定義 lse

題目鏈接 https://nanti.jisuanke.com/t/38222

題意:

定義函數:

$$F(n)=\left\{
\begin{aligned}
1, \quad n=1,2 \\
F(n-1)+F(n-2),\quad n\geq3 \quad
\end{aligned}
\right.
$$

給定一個W 找到一個字典序最小的集合S使得

$$W=\sum_{f\in S}F(F(f))$$

$1\leq T\leq 10$

$1\leq W\leq 10^{100,000}$

解析:java大數打表可以發現 當f >28時已經超過W上界了,所以快速冪求出來前28項就好了,數增加的非常快,只有當W<=10時才有 多個解的情況

所以從大的開始減,當減到第五項的時候 再分類討論一下就好了。

AC代碼

import java.util.*;
import java.math.*;

public class Main {
   
    static class Matrix {
        public static  int maxn = 2;
        BigInteger a[][] = new BigInteger [maxn][maxn];
        public void init() {
            for (int i = 0; i < maxn; ++i) for
(int j = 0; j < maxn; ++j) a[i][j] = BigInteger.ZERO; } public void _init() { init(); for (int i = 0; i < maxn; ++i) a[i][i] = BigInteger.ONE; } public static Matrix mul(Matrix A, Matrix B) { Matrix res = new Matrix(); res.init();
for (int i = 0; i < maxn; ++i) { for (int j = 0; j < maxn; ++j) { for (int k = 0; k < maxn; ++k) { res.a[i][k] = res.a[i][k].add(A.a[i][j].multiply(B.a[j][k])); } } } return res; } public static Matrix q_pow(Matrix A, BigInteger k) { Matrix res = new Matrix(); res._init(); while(k.compareTo(BigInteger.ZERO) > 0) { if(k.mod(BigInteger.valueOf(2)).compareTo(BigInteger.ZERO) > 0) res = mul(res, A); A = mul(A, A); k = k.shiftRight(1); } return res; } } public static BigInteger get_fib(BigInteger n) { if(n.compareTo(BigInteger.ONE) == 0) return BigInteger.ONE; if(n.compareTo(BigInteger.valueOf(2)) == 0) return BigInteger.ONE; Matrix A = new Matrix(); A.a[1][1] = BigInteger.ZERO; A.a[0][0] = A.a[1][0] = A.a[0][1] = BigInteger.ONE; A = Matrix.q_pow(A, n.subtract(BigInteger.valueOf(2))); return A.a[0][0].add(A.a[0][1]); } public static void main(String[] args) { BigInteger f[] = new BigInteger[100]; int ans[] = new int[100]; Scanner cin = new Scanner(System.in); int T = cin.nextInt(); for (int i = 1; i <= 28; ++i) { f[i] = Main.get_fib(Main.get_fib(BigInteger.valueOf(i))); } while(T--> 0) { BigInteger W = cin.nextBigInteger(); int cnt = 0; for (int i = 28; i >= 6; --i) { if(f[i].compareTo(W) <= 0) { ans[++cnt] = i; W = W.subtract(f[i]); } } if(W.compareTo(BigInteger.valueOf(1)) == 0) { ans[++cnt] = 1; } else if(W.compareTo(BigInteger.valueOf(2)) == 0){ ans[++cnt] = 2; ans[++cnt] = 1; } else if(W.compareTo(BigInteger.valueOf(3)) == 0) { ans[++cnt] = 3; ans[++cnt] = 2; ans[++cnt] = 1; } else if(W.compareTo(BigInteger.valueOf(4)) == 0) { ans[++cnt] = 4; ans[++cnt] = 2; ans[++cnt] = 1; } else if(W.compareTo(BigInteger.valueOf(5)) == 0) { ans[++cnt] = 4; ans[++cnt] = 3; ans[++cnt] = 2; ans[++cnt] = 1; } else if(W.compareTo(BigInteger.valueOf(6)) == 0) { ans[++cnt] = 5; ans[++cnt] = 1; } else if(W.compareTo(BigInteger.valueOf(7)) == 0) { ans[++cnt] = 5; ans[++cnt] = 2; ans[++cnt] = 1; } else if(W.compareTo(BigInteger.valueOf(8)) == 0) { ans[++cnt] = 5; ans[++cnt] = 3; ans[++cnt] = 2; ans[++cnt] = 1; } else if(W.compareTo(BigInteger.valueOf(9)) == 0) { ans[++cnt] = 5; ans[++cnt] = 4; ans[++cnt] = 2; ans[++cnt] = 1; } else if(W.compareTo(BigInteger.valueOf(10)) == 0) { ans[++cnt] = 5; ans[++cnt] = 4; ans[++cnt] = 3; ans[++cnt] = 2; ans[++cnt] = 1; } else if(W.compareTo(BigInteger.ZERO)!=0){ System.out.println(-1); continue; } for (int i = cnt; i >= 1; --i) { if(i == 1) System.out.println(ans[i]); else System.out.print(ans[i]+" "); } } } }

代碼參考 https://www.cnblogs.com/widsom/p/10742707.html

2019南昌邀請賽 C. Angry FFF Party 大數矩陣快速冪+分類討論