J - 金色传说 Gym - 102174J (简单DP)
题目链接:
J - 金色传说
题目大意:
合法的表达式个数。
具体思路:
因为有加减,所以当我们枚举到某一位的时候,如果当前这一位是加号或者减号,那么后面的就可以抵消掉了,所以这是一个很大的优化,但是注意这种情况前面的会重复加,所以需要计算出重复的次数。
len[i]代表当长度为i的合法情况总数。
sum[i]代表长度为i并且为纯数字的情况总数。
所以len[n] = sigma((1<=i<=n-2))(sum[n-i-1]*2*len[i]);
AC代码:
1 #include<bits/stdc++.h>
2 using namespace std;
3 # define inf 0x3f3f3f3f
4 # define ll long long
5 const int maxn = 2e6+100;
6 const int N = 5e5+10;
7 const int mod = 998244353;
8 ll sum[maxn],len[maxn];
9 ll qsm(ll t1,ll t2)
10 {
11 ll res=1ll;
12 while(t2)
13 {
14 if(t2&1)
15 res=res*t1%mod;
16 t2>>=1;
17 t1=t1*t1%mod;
18 }
19 return res;
20 }
21 void init()
22 {
23 sum[1]=45ll;
24 sum[2]=4950ll;
25 len[1]=10ll;
26 len[2]=100ll;
27 for(int i=3; i<N; i++)
28 {
29 ll tmp=qsm(10ll,i);
30 sum[i]=(tmp*(tmp-1ll)/2%mod);
31 len[i]=(10ll*2ll*len[i-2]%mod+10ll*len[i-1]%mod)%mod;
32 }
33 }
34 int main()
35 {
36 init();
37 int T;
38 scanf("%d",&T);
39 while(T--)
40 {
41 int n;
42 scanf("%d",&n);
43 ll ans=sum[n];
44 for(int i=1; i<=n-2; i++)
45 {
46 ans=(ans+sum[n-i-1]*2ll*len[i])%mod;
47 }
48 printf("%lld\n",ans%mod);
49 }
50 return 0;
51 }