**
https://codeforces.com/problemset/problem/1513/C
**
Add One
思路1
记录开始时每个0-9每个数字的个数,然后模拟每次的变化,每操作一次就需要对0-9都进行一次运算处理
明显会超时,但还是写了一下
#include<iostream>
#include<vector>
#include<string>
#include<queue>
#include<map>
#include<algorithm>
#include<iomanip>
#include <stdio.h>
#include<memory.h>
#include<stdio.h>
#include<math.h>
#include <fstream>
#include<stack>
using namespace std;
#define ll long long
const int MAX = 1000000007;
int main()
{
int t;
cin >> t;
int a[10];
while (t--)
{
memset(a, 0, sizeof(a));
ll ans = 0;
int b, c;
cin >> b >> c;
while (b)
{
a[b % 10]++;
b = b / 10;
ans++;
}
int befor,next;
while (c--)
{
befor = a[0];
for (int i = 1; i < 10; i++)
{
if (i == 9)
{
a[1] += a[i] % MAX;
a[0] = a[i] % MAX;
ans += a[i] % MAX;
}
next = a[i];
a[i] = befor;
befor = next;
}
}
cout << ans << endl;;
}
}
思路2
经过思路一之后就想能不能直接算出n个0,n个1,n个2操作m次之后会增加多少位。
进一步推出,每个数变化十次之后就会生成一个自身和比自身大一的数。
这样可以将复杂度降低一些。
#include<iostream>
#include<vector>
#include<string>
#include<queue>
#include<map>
#include<algorithm>
#include<iomanip>
#include <stdio.h>
#include<memory.h>
#include<cstdio>
#include<math.h>
#include <fstream>
#include<stack>
using namespace std;
#define ll long long
const int MAX = 1000000007;
int main()
{
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
int t;
cin >> t;
int a[10];
while (t--)
{
memset(a, 0, sizeof(a));
ll ans = 0;
int b, c;
cin >> b >> c;
while (b)
{
a[b % 10]++;
b = b / 10;
ans++;
}
int befor, next;
while (c)
{
if (c >= 10)
{
int f;
for (int i = 9; i >= 0; i--)
{
if (i == 9)
{
f = a[i] % MAX;
ans += 2 * a[i] % MAX;
}
else
{
a[i + 1] += a[i] % MAX;
ans += a[i] % MAX;
}
}
a[0] += f;
a[1] += f;
c -= 10;
}
else
{
for (int i = 10 - c; i < 10; i++)
{
ans += a[i] % MAX;
}
c = 0;
}
}
ans %= MAX;
cout << ans << endl;;
}
}
依然过不了
思路三
经过思路一之后就想能不能直接算出n个0,n个1,n个2操作m次之后会增加多少位。虽然无法直接计算出n个x变化m次后增加多少位,但是只要算出0操作m次后变成多少位就可以计算出1,2,3,m次后的位数,因为可以将1,2,3,分别认为是0经过一次两次三次操作得到的,后续是一样的,然后再统计输入中每个数字的个数,a1,a2,a3,答案就是a1p[m+x1]+a2p[m+x2]
这个能过了但是还是有更简单的方法。
#include<iostream>
#include<vector>
#include<string>
#include<queue>
#include<map>
#include<algorithm>
#include<iomanip>
#include <stdio.h>
#include<memory.h>
#include<cstdio>
#include<math.h>
#include <fstream>
#include<stack>
using namespace std;
#define ll long long
const int MAX = 1000000007;
int a[10];
ll p[200050];
int main()
{
int t;
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
int c, befor, next;
ll ans;
int j = 0;
memset(a, 0, sizeof(a));
a[j] = 1;
c = 200020;
ans = 1;
while (c--)
{
befor = a[0];
for (int i = 1; i < 10; i++)
{
if (i == 9)
{
a[1] += a[i] % MAX;
a[0] = a[i] % MAX;
ans += a[i] % MAX;
}
next = a[i] % MAX;
a[i] = befor% MAX;
befor = next;
}
p[200020 - c] = ans% MAX;
}
cin >> t;
while (t--)
{
memset(a, 0, sizeof(a));
ans = 0;
string b;
cin >> b >> c;
for (int i = 0; i < b.size(); i++)
a[b[i] - '0']++;
if (c != 0)
{
for (int i = 0; i < 10; i++)
{
ans += a[i] * p[c + i];
ans %= MAX;
}
}
cout << ans << endl;;
}
}
思路四
经过分析思路三得出的数组p知道了当i>10时p[i]=p[i-10]+p[i-9]
正是思路二的反推这样就可以简单的算出思路三中的p数组了。
但是运行速度并没有明显差距。
#include<iostream>
#include<vector>
#include<string>
#include<queue>
#include<map>
#include<algorithm>
#include<iomanip>
#include <stdio.h>
#include<memory.h>
#include<stdio.h>
#include<math.h>
#include <fstream>
#include<stack>
using namespace std;
#define ll long long
const int MAX = 1000000007;
ll p[200050];
int main()
{
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
int t;
ll ans;
for (int i = 0; i < 10; i++)
p[i] = 1;
p[10] = 2;
for (int i = 11; i < 200050; i++)
{
p[i] = p[i - 10] % MAX + p[i - 9] % MAX;
p[i] = p[i] % MAX;
}
cin >> t;
while (t--)
{
ans = 0;
string b;
int c;
cin >> b >> c;
for (int i = 0; i < b.size(); i++)
ans += p[b[i] - '0' + c],ans%=MAX;
cout << ans << endl;;
}
}