ATCoder_contest_abc220
D-FG operation
题目描述
我们有一个包含N个整数的序列,每个整数在0~9之间(包含0和9):A = (\(A_1\),......,\(A_n\)),被按照这个序列进行排列。我们将进行F操作和G操作,直到这个序列的长度为一。
- 操作F:删除最左端的两个数(x1,x2),将(x1+x2)%10加到序列的最左端
- 操作G:删除最左端的两个数(x1,x2),将(x1*x2)%10加到序列的最左端
对于每一个k = 0,1,2,...,9
在 2 的 N 次方减一种可能的方法中,有多少种操作方法,使得最后剩余的数字是 K。由于这个结果可能非常的大,请输出这个结果对998244353取模后的结果。
数据规模
2 <= N <= 1e5
0 <= \(A_i\) <= 9
原题链接
Input
3
2 7 6
Output
1
0
0
0
2
1
0
0
0
0
Input
5
0 1 2 3 4
Output
6
0
1
1
4
0
1
1
0
2
题解思路
对于一个长度为 N 的序列,可以先考虑最前面的两项,然后结果存到第二个位置上,第二个位置上有两种可能,一是分别进行F和G操作是产生了两个不同的数字,二是产生了两个相同的数字。这个时候,虽然第二个位置有很多种情况,但是对于给定的\(A_1\),\(A_2\),我们一定可以算出所有的可能,然后拿\(A_2\)位置上的所有可能与\(A_3\)进行F,G操作,\(A_3\)有可以算出来。然后要做的就是存了,我是开了一个arr[N][10]的数组,arr[i][9]表示把前 i-1 项消除之后第 i 位(即此时的第一位)剩余数字为 9,这样的方法有多少种。怎么更新呢?是个递推啊。假设arr[i-1][0~9]我们都知道,\(A_i\)是题目给出的,我们拿\(A_i\)对 0~9 分别进行F,G操作,比如 \(A_i\) = 3,当他对 0 进行F操作时,结果为3,我就让arr[i][3] += arr[i-1][0],当进行G操作时,结果也为3,我们就再arr[i][3] += arr[i-1][0],其他数字亦是如此。也就是说我们知道前一个的结果,可以推出后一个的结果,上代码。
AC代码
#include <iostream>
#define int long long
using namespace std;
const int N = 1e5 + 10;
const int mod = 998244353;
int arr[N][10],n;
signed main(){
cin >> n;
for(int i = 1; i <= n; i++){
int a;
cin >> a;
arr[i][a]++; //初始化,记录第 i 个位置 Ai 的值(做标记)
}
for(int i = 2; i <= n; i++){
int temp;
for(int j = 0; j < 10; j++)
if(arr[i][j] == 1) temp = j,arr[i][j] = 0; //取出Ai,并把arr[i][j]归零(删除标记)
for(int j = 0; j < 10; j++){
arr[i][(j + temp) % 10] = (arr[i][(j + temp) % 10] + arr[i-1][j]) % mod;
arr[i][(j * temp) % 10] = (arr[i-1][j] + arr[i][(j * temp) % 10]) % mod;
}
}
for(int i = 0; i < 10; i++)
cout << arr[n][i] << endl;
return 0;
}

浙公网安备 33010602011771号