题解:P17074 [ICPC 2017 Shenyang R] New Self-describing Sequence
妙妙 trick。相似题(更复杂)推荐:P14473。
性质
容易发现每次只会增加各位数字之和,这个东西很小,只有
分析
我们尝试从高往低去确定每一位的答案是多少。那么我就要快速的知道从一个形如
我们通过从
想想除了需要多少步,我们还需要知道哪些信息:设
::::info[解释一下
即可以理解为将
接下来考虑转移。
首先考虑初状态,即
接下来对于
于是我们考虑合并两个状态,即在
假设两状态分别为
然后就是求每一位的值了。借助前面预处理好的 dp 数组,我们可以很快的求出将一个高位进一位的一些信息。最后剩下
code
::::success[code]
#include<bits/stdc++.h>
#define ll long long
#define lll __int128
using namespace std;
const int mod=1e9+9;
int t;
ll n;
struct node{
lll c,x,sum;
int z;
node operator +(const node &y)const{
return {c+y.c,x+y.x,(sum+y.sum+x*y.c)%mod,y.z};
}
}f[200][20][1000];
void out(lll x){
if(!x) return;
out(x/10);
putchar(x%10+'0');
}
void write(node x){
out(x.x);
putchar(' ');
out(x.sum);
putchar('\n');
}
int digit(lll x){
int cnt=0;
while(x){
cnt+=x%10;
x/=10;
}
return cnt;
}
void init(){
for(int c=0;c<200;c++){
for(int i=0;i<1000;i++){
if(!(i+c)) continue;
int j=i;
while(j<1000){
int k=c+digit(j);
j+=k;
f[c][0][i].c++,f[c][0][i].x+=k,f[c][0][i].sum=(f[c][0][i].sum+f[c][0][i].x)%mod;
}
f[c][0][i].z=j%1000;
}
}
for(int i=1;i<=17;i++){
for(int c=0;c<200;c++){
for(int j=0;j<1000;j++){
f[c][i][j].z=j;
for(int d=0;d<10&&c+d<200;d++){
f[c][i][j]=f[c][i][j]+f[c+d][i-1][f[c][i][j].z];
}
}
}
}
}
node work(ll n){
node nw={1,1,1,1};
int ds=0;
for(int i=17;i>=0;i--){
for(int j=1;j<10;j++){
if(nw.c+f[ds][i][nw.z].c<=n){
nw=nw+f[ds][i][nw.z];
ds++;
}
}
}
while(nw.c<n){
int xx=digit(nw.x);
nw.c++,nw.x+=xx,nw.sum=(nw.sum+nw.x)%mod;
}
return nw;
}
int main(){
init();
cin>>t;
for(int T=1;T<=t;T++){
scanf("%lld",&n);
printf("Case #%d: ",T);
write(work(n));
}
return 0;
}
::::