本文已参与「新人创作礼」活动, 一起开启掘金创作之路。
【Codeforces】Codeforces Round #742 (Div. 2) C. Carrying Conundrum | 动态规划、思维
题目链接
题目
题目大意
对于给定的 输出满足 的不同有序正整数对 的数量,在本题中 +
的进位规则从“满 10 向高一位进 1”变为“满 10 向高二位进 1”。如 。
动态规划
思路
一开始读懂题没敢下手做,不理解数据范围为啥只给到 ,感觉 比较合适 QAQ
容易发现虽然这个题里的进位规则有所改变,但依然是要么进 1 要么不进位。所以我们可以考虑 DP。将 由低位向高位写成 。令 表示前 个元素乱选且满足要求的方案其中第 位不进位, 表示前 个元素乱选且满足要求的方案其中第 位进位。怎么转移呢?
首先手玩出两个一位数相加和为 的方案放在数组 里,然后我们从低到高遍历输入的 的每一位 ,显然有(即从 进不进位分别转移):
容易发现奇偶位置方案相互独立,由乘法原理最终的方案为 。
注意:
- 转移和输出答案过程中可能出现越界问题,需要进行特判。
- 模数是 ……
- 由于要求 和 均为正整数,答案需要减去带有 0 的情况,所以应该输出 。
代码
#include <iostream>
#include <algorithm>
#include <math.h>
#include <stdio.h>
#include <map>
#include <vector>
#include <queue>
using namespace std;
using LL=long long;
const int N=11;
int n,tot,a[N];
LL dp[N][2];
LL qwq[21]={1,2,3,4,5,6,7,8,9,10,9,8,7,6,5,4,3,2,1,0};
LL solve()
{
scanf("%d",&n);
for (tot=0;n;n/=10) a[++tot]=n%10;
dp[1][0]=qwq[a[1]];
dp[1][1]=qwq[a[1]+10];
if (tot==1) return printf("%d\n",dp[1][0]-2),0;
dp[2][0]=qwq[a[2]];
dp[2][1]=qwq[a[2]+10];
for (int i=3;i<=tot;++i)
{
dp[i][0]=qwq[a[i]]*dp[i-2][0];
if (a[i]) dp[i][0]+=qwq[a[i]-1]*dp[i-2][1];
dp[i][1]=qwq[a[i]+10]*dp[i-2][0]+qwq[a[i]+9]*dp[i-2][1];
}
printf("%lld\n",dp[tot][0]*dp[tot-1][0]-2);
return 0;
}
int main()
{
int T=1;
scanf("%d",&T);
while (T--) solve();
return 0;
}
推式子直接输出
思路
看了题解大惊失色(
我们刚才指出了
容易发现奇偶位置方案相互独立
那么实际上将 的每个数位直接按照奇偶分开,顺序连成两个数字 和 ,原先的进两位就变成的普通的进位……如 可以划分成 和 。那么一个数字 划分成两个数之和的方案数显然就是 ,所以直接输出 即可。