补一下codeforces前天教育场的题。当时只A了一道题。
大致题意:
定义一个x - y - counter :是一个加法计数器。初始值为0,之后可以任意选择+x或者+y而我们由每次累加结果的最后一位生成一个数列。
例如:4 - 2 - counter 进行+4 +4 +4 +4 +2 +4操作会生成数列 04824。每步要加上x或y是任意的。
给你一个数列(由0~9组成的字符串),问你0~9中全部两个数字生成这个包含这个子串的数列中间至少要插入多少数字。以10 * 10矩阵格式输出。
例如:给定字符串:0840 用 4 - 3 - counter 生成 0(4)8(1)4(7)0是插入数字最少的数列,那么第四行第三列就是3。
样例输入:
0840
样例输出:
-1 17 7 7 7 -1 2 17 2 7
17 17 7 5 5 5 2 7 2 7
7 7 7 4 3 7 1 7 2 5
7 5 4 7 3 3 2 5 2 3
7 5 3 3 7 7 1 7 2 7
-1 5 7 3 7 -1 2 9 2 7
2 2 1 2 1 2 2 2 0 1
17 7 7 5 7 9 2 17 2 3
2 2 2 2 2 2 0 2 2 2
7 7 5 3 7 7 1 3 2 7
思路:
照着涛哥的代码和思路自己理解了一下。然后敲了一遍。
首先用dp思想初始以x,y为加数加一个个位数为mod的数的的最小步数,因为每步都会在中间插入一个数所以最小步数即在两个
数中间出现的最少的字符+1。生成这个数组i,j循环到9就可以了。然后在打印矩阵中就是算出字符串中每两个数的差值,直接代
入dp[x][y][s[i] - s[i - 1]] - 1即可。转移方程:dp[x][y][mod] = min{i + j} ((i * x + j * y) % 10 == mod)
代码:
1 /*
2 2019年8月10日16点43分
3 Time
4 936ms
5 Memory
6 5312kB
7 Length
8 1497*/
9 #include <cstdio>
10 #include <cstring>
11 #include <string>
12 #include <iostream>
13 using namespace std;
14
15 typedef long long ll;
16 const int MAXN = 50;
17 const int INF = 0x7f7f7f7f;
18
19 ll dp[MAXN][MAXN][MAXN];
20
21 void fill()
22 {
23 for(int i = 0; i < 10; i ++)
24 for(int j = 0; j < 10; j ++)
25 for(int k = 0; k < 10; k ++)
26 dp[i][j][k] = INF;
27 return;
28 }
29 void init()
30 {
31 fill();
32 for(int x = 0; x < 10; x ++)
33 for(int y = 0; y < 10; y ++){
34 for(int i = 0; i < 10; i ++) // i, j只从0循环到9就可以找到x - y - counter生成mod的最少步数。
35 for(int j = 0; j < 10; j ++){
36 if(i + j == 0) continue; // 0 - 0 - counter因为无法生成任何数所以直接跳过。
37 int mod = (i * x + j * y) % 10;
38 dp[x][y][mod] = min(dp[x][y][mod], 1ll * (i + j)); // 进行状态转移。
39 }
40 }
41 return ;
42 }
43
44 ll cal(int x, int y, int a, int b)
45 {
46 a -= b; // 计算的时候因为是从上一位数要加到这一位所以先减去b,是对10取模,+10不影响。
47 if(a < 0) a += 10;
48 return dp[x][y][a];
49 }
50
51 int main()
52 {
53 string s;
54 cin >> s;
55
56 init();
57
58 int n = s.length();
59 for(int x = 0; x < 10; x ++){
60 for(int y = 0; y < 10; y ++){
61 ll ans = 0;
62 for(int i = 1; i < n; i ++){
63 ll cnt = cal(x, y, s[i] - '0', s[i - 1] - '0');
64 ans += cnt; // 把每一位数都算上,然后输出这个位置的答案。
65 if(ans >= INF) break;
66 ans --; // 要减一是因为最后一个数就是我们要的,但不算到中间插入的数。
67 }
68
69 if(ans >= INF) printf("-1 ");
70 else printf("%lld ", ans);
71 }
72 printf("
");
73 }
74 return 0;
75 }
感受:
涛哥tql!