不降数
首先暴力打表,寻找规律;
/*
1 1 1 1 1 1 1 1 1 (0~9)
9 8 7 6 5 4 3 2 1 (10~99)
45 36 28 21 15 10 6 3 1 (100~999)
165 120 84 56 35 20 10 4 1 (1000~9999)
495 330 210 126 70 35 15 5 1 (10000~99999)
*/
以第二行为例,9是10~19的总数;8是20~29的总数;
以第三行为例,45是100~199的总数;以此类推
我们容易发现,下一行的第一位,就是上一行的总和;
下一行的第二位,就是上一行的第二位到第九位的总和;
以此类推;
然后我们就可以写出这样的一段代码
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
int f[15];
const int MOD = 100019;
/*
1 1 1 1 1 1 1 1 1
9 8 7 6 5 4 3 2 1
45 36 28 21 15 10 6 3 1
165 120 84 56 35 20 10 4 1
495 330 210 126 70 35 15 5 1
*/
int read(){
int x=0;bool f=0;char c=getchar();
while (c<'0'||c>'9'){if (c=='-')f=1;c=getchar();}
while (c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
return f?-x:x;
}
void write(int x)
{
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10+'0');
}
int main()
{
int n;
n=read();
if(n<2) {
putchar('9');
}else{
for(int i=1;i<=9;i++) f[i]=10-i;
int sum = 0;
for(int i=2;i<=n;i++){
sum = 0;
for(int j=9;j>=1;j--){
//算上一行的和 填下一行的值
sum+=f[j];
f[j]=sum%MOD;
}
}
write(f[1]);
}
return 0;
}
然后T了,,快读快写都用上了…
本来以为能水过去的,毕竟数据是10^8还是有机会的;
于是查看题解,发现了可以用矩阵快速幂来加速;
首先构造矩阵
B就是0~9分别对应的9个数,我们发现B左乘一次A;
就得到了10~99对应的9个数;
再左乘一次A,就得到了100~999对应的9个数
/*
1 1 1 1 1 1 1 1 1 (0~9)
9 8 7 6 5 4 3 2 1 (10~99)
45 36 28 21 15 10 6 3 1 (100~999)
165 120 84 56 35 20 10 4 1 (1000~9999)
495 330 210 126 70 35 15 5 1 (10000~99999)
*/
因为题目要求的是n位的总和;
那么我们只需要计算A^(n-1)×B
就可以得到一个9×1列的矩阵,然后累加这九个数字,就是答案了;
Code
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int MOD = 100019;
typedef long long ll;
/*
1 1 1 1 1 1 1 1 1 0~9
9 8 7 6 5 4 3 2 1 10~99
45 36 28 21 15 10 6 3 1 100~999
165 120 84 56 35 20 10 4 1 1000~9999
495 330 210 126 70 35 15 5 1 10000~99999
*/
struct Mat{
ll c[15][15];
}E,A,B;
Mat mul(Mat x,Mat y){
Mat ret;
for(int i=1;i<=9;i++)
for(int j=1;j<=9;j++) ret.c[i][j]=0;
for(int i=1;i<=9;i++){
for(int j=1;j<=9;j++){
for(int k=1;k<=9;k++){
ret.c[i][j]=(ret.c[i][j]%MOD+x.c[i][k]*y.c[k][j]%MOD)%MOD;
}
}
}
return ret;
}
//x^y
Mat q_pow(Mat x,ll y){
Mat ret = E;
Mat base = x;
while(y){
if(y&1){
ret=mul(ret,base);
}
base=mul(base,base);
y>>=1;
}
return ret;
}
void print_Mat(Mat A){
for(int i=1;i<=9;i++){
for(int j=1;j<=9;j++){
cout << A.c[i][j] << ' ';
}
cout << '\n';
}
}
void init(){
for(int i=1;i<=9;i++)
for(int j=i;j<=9;j++)
A.c[i][j]=1;
for(int i=1;i<=9;i++) B.c[i][1]=E.c[i][i]=1;
}
int main()
{
init();
int n;
cin >> n;
Mat powA =q_pow(A,n-1);
B = mul(powA,B);
ll ans = 0;
for(int i=1;i<=9;i++) {
ans=ans+B.c[i][1];
ans%=MOD;
}
cout << ans << '\n';
return 0;
}