参考于:xls tql
若存在a+b,那么一定存在一个a-b,两者求和,2*a,所以对于每个长度为n和合法式子,只需对每个式子第一个 +/- 前面数字求和,所以需要统计 + / - 号前面的a出现多少次。
假设第一个 + / - 前面是一个长度为i的数字,那么 + / - 号后面有 n - i - 1位,每个长度为i的数字出现次数 = 2(正负两种情况) * 长度为 n - i -1 合法式子的种数。 因为每个长度为 i 的数字出现次数相同,所以先对长度为 i 的数字求和,前导0也算,用等差数列求和公式(1 + (10 ^ i - 1))*(10 ^ i - 1) / 2 。sum += 长度为i的数字总和 * 2 * 长度为 n - i -1 合法式子的种数。现在只需要求长度为 n - i -1 合法式子的种数。
dp[i]表示长度为i合法式子的种数,
长度为i合法式子有两种来源,
- 在长度为i-1合法式子后面添加一个数字
- 在长度为i-2合法式子后面添加一个符号和一个数字
所以 dp[i] = dp[i-1] * 10 + dp[i-2] *2 *10
#include<bits/stdc++.h>
using namespace std;
const int N = 5e5 + 100;
#define mod 998244353
typedef long long ll;
int t,n;
ll d[N], dp[N];
int main(){
d[0] = 0;
d[1] = 45; //所有长度小于等于i数字的和
ll p=10;
for(int i = 2; i <= 5e5; i++){
p = p * 10 % mod;
d[i] = p * (p - 1) / 2 % mod;//长度为i的序列和=(1+10^i-1)*(10^i-1)/2
}
dp[0] = 0;
dp[1] = 10; //长度为i的合法数字列的数量
for(int i = 2; i <= 5e5; i++) {
dp[i] = (dp[i-1] * 10 % mod + dp[i-2] * 20 %mod) %mod;
//长度为i的合法序列可以由 长度i-1的合法序列加一个数字得到
//也可以由长度为i-2的合法序列加上一个符号和数字得到
}
cin >> t;
while(t--){
cin >> n;
int res = d[n];
for(int i = n-1; i >= 1; i--){
res = (res + d[i] * 2 * dp[n-i-1] % mod) % mod;
}
cout << res << "\n";
}
return 0;
}