1013. K-based Numbers. Version 3
Time limit: 0.5 second
Memory limit: 64 MB
Memory limit: 64 MB
Let’s consider
K-based numbers, containing exactly
N digits. We define a number to be valid if its
K-based notation doesn’t contain two successive zeros. For example:
- 1010230 is a valid 7-digit number;
- 1000198 is not a valid number;
- 0001235 is not a 7-digit number, it is a 4-digit number.
Given three numbers
N,
K and
M, you are to calculate an amount of valid
K based numbers, containing
N digits modulo
M.
You may assume that 2 ≤
N,
K,
M ≤ 10
18.
Input
The numbers
N,
K and
M in decimal notation separated by the line break.
Output
The result in decimal notation.
Sample
input | output |
---|---|
2 10 100 | 90 |
Difficulty: 221
Printable version
Submit solution
Discussion (52)
All submissions (4500) All accepted submissions (880) Solutions rating (613)
首先这是前面两个题的升级版,具体解释可参考前面的题目;
1.URAL 1009. K-based Numbers [递推DP]
2.K-based Numbers. Version 2 URAL - 1012 [dp + java大数]
根据之前的dp,可以总结出一个规律:dp[ i ] = (dp[ i - 1 ] + dp[ i - 2 ])*(k - 1);
推导的话,我贴张图吧,希望能看懂
所以这就是个fib变形吧。。。
现在n非常大,那么我用矩阵快速幂+java大数解决!
代码:
//package com.company;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.DecimalFormat;
import java.util.Scanner;
//import static com.company.Main.quickp;
public class Main {
static BigInteger n;
static BigInteger k ;
static BigInteger m ;
static BigInteger A[][];
static BigInteger B[][];
public static void init(){
A = new BigInteger[2][2];
B = new BigInteger[2][2];
A[0][0] = k.subtract(BigInteger.ONE);
A[0][1] = k.subtract(BigInteger.ONE);
A[1][0] = BigInteger.ONE;
A[1][1] = BigInteger.valueOf(0);
B[0][0] = k.subtract(BigInteger.ONE);
B[0][1] = BigInteger.valueOf(0);
B[1][0] = BigInteger.valueOf(0);
B[1][1] = BigInteger.valueOf(0);
}
public static void mult(BigInteger a[][], BigInteger b[][])
{
BigInteger ans[][] = new BigInteger[2][2];
for(int i = 0; i < 2; i++)
for(int j = 0; j < 2; j++)
ans[i][j] = BigInteger.valueOf(0);
for(int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
for (int k = 0; k < 2; k++) {
ans[i][j] = ans[i][j].add(a[i][k].multiply(b[k][j]));
ans[i][j] = ans[i][j].remainder(m);
}
}
}
for(int i = 0; i < 2; i++)
for(int j = 0; j < 2; j++)
a[i][j] = ans[i][j];
}
public static BigInteger[][] quickp(BigInteger b)
{
BigInteger a[][] = new BigInteger[2][2];
a[0][0] = BigInteger.ONE;
a[1][1] = BigInteger.ONE;
a[0][1] = BigInteger.valueOf(0);
a[1][0] = BigInteger.valueOf(0);
while (b != BigInteger.valueOf(0))
{
if((b.remainder(BigInteger.valueOf(2))).equals(BigInteger.ONE))
mult(a, A);
//System.out.println(a[0][0]);
mult(A, A);
b = b.divide(BigInteger.valueOf(2));
}
return a;
}
public static void main(String[] args) {
Scanner scanf = new Scanner(System.in);
n = scanf.nextBigInteger();
k = scanf.nextBigInteger();
m = scanf.nextBigInteger();
init();
A = quickp(n.subtract(BigInteger.ONE));
mult(A, B);
A[1][0] = A[1][0].add(A[0][0]);
System.out.println(A[1][0].remainder(m));
}
}