题目链接 : Click here
We define a kind of strings as elegant string: among all the substrings of an elegant string, none of them is a permutation of "0, 1,…, k".
Let function(n, k) be the number of elegant strings of length n which only contains digits from 0 to k (inclusive). Please calculate function(n, k).
Input
Input starts with an integer T (T ≤ 400), denoting the number of test cases.
Each case contains two integers, n and k. n (1 ≤ n ≤ 10
18) represents the length of the strings, and k (1 ≤ k ≤ 9) represents the biggest digit in the string.
Output
For each case, first output the case number as "
Case #x: ", and x is the case number. Then output function(n, k) mod 20140518 in this case.
Sample Input
2 1 1 7 6
Sample Output
Case #1: 2 Case #2: 818503
Source
思路。。
如果认真想条件的话。。 其实发现他就是一个DP。。
只不过N太大。。需要用矩阵来算。。
dp[i][j] , i 表示字符串长度。 j 表示与当前数不同的个数。。
则有 dp[i][j] = dp[i-1][j-1] * (k-j+1) + dp[i-1][j] + dp[i-1][j] .... + dp[i-1][k-1];
用代码写出就是。
#include <bits/stdc++.h>
using namespace std;
int dp[100][100]={0};
const int MOD = 20140518;
int n,k;
int main(){
while(scanf("%d %d",&n,&k)!=EOF){
memset(dp,0,sizeof(dp));
dp[1][0]=k+1;
for(int i = 1;i <= n;i++)
for(int j = 0;j < k;j++){
if(j>0)
dp[i][j] = (dp[i][j] + dp[i-1][j-1]*(k-j+1)) % MOD;
for(int z = j; z < k;z++){
dp[i][j] = (dp[i][j] + dp[i-1][z]) % MOD;
}
//printf("dp[%d][%d]=%d\n",i,j,dp[i][j]);
}
//printf("\n");
int sum = 0;
for(int i = 0;i < k;i++){
sum = (sum + dp[n][i]) % MOD;
//printf("dp[%d][%d]=%d\n",n,i,dp[n][i]);
}
printf("%d\n",sum);
}
return 0;
}
但由于N太大。。用矩阵方法写就是
#include <bits/stdc++.h>
using namespace std;
/*
origin matrix
k+1 0 0 0 0 0 0 0 there is k-1 zero
right matrix
there is k row k col
1 k 0 0 0
1 1 k-1 0 0
1 1 1 k-2 0
1 1 1 0 k-3
1 1 1 0 0
1 1 1 0 0
*/
const int MOD = 20140518;
struct Matrix{
int mat[12][12];
int n;
void init(int _n){
memset(mat,0,sizeof(mat));
n = _n;
}
Matrix operator *(const Matrix &b)const
{
Matrix ret;
ret.n = n;
for(int i = 0;i < n;i++)
for(int j = 0;j < n;j++)
{
ret.mat[i][j] = 0;
for(int k = 0;k < n;k++)
{
ret.mat[i][j] += (long long)mat[i][k]*b.mat[k][j]%MOD;
if(ret.mat[i][j] >= MOD)
ret.mat[i][j] -= MOD;
}
}
return ret;
}
void print(){
for(int i = 0;i < n;i++){
for(int j = 0;j < n;j++)
printf("%d ",mat[i][j]);
printf("\n");
}
}
};
Matrix pow_M(Matrix a,long long n)
{
Matrix ret;
ret.init(a.n);
for(int i = 0;i < a.n;i++)
ret.mat[i][i] = 1;
Matrix tmp = a;
while(n)
{
if(n&1)ret = ret*tmp;
tmp = tmp*tmp;
n >>= 1;
}
return ret;
}
long long n;
int k;
int main(){
int cas,tt=0;
scanf("%d",&cas);
while(cas--){
cin >> n >> k;
//printf("k=%d\n",k);
Matrix left,right; left.init(k),right.init(k);
left.mat[0][0] = k+1;
for(int i=0;i<k;i++)
for(int j=i;j<k;j++){
right.mat[j][i] = 1;
}
for(int i=1;i<k;i++)
right.mat[i-1][i] = k-i+1;
//right.print();
right = pow_M(right,n-1);
left = left * right;
long long ans = 0;
for(int i = 0;i < k;i++){
ans += left.mat[0][i];
ans %= MOD;
}
printf("Case #%d: %d\n",++tt,(int)ans);
}
return 0;
}
已解决。。