C. Add One

19 篇文章 0 订阅
4 篇文章 0 订阅

C. Add One

题目连接

题目大意
给你一个数然后进行k次操作,要求让你对每一位加一。问k次操作后这个数会变成多少位。

思路

每一位加一变化时,只有9加一会多变出一位,那么进行预处理,用二维数组进行dp,先看9加1到10,多出1位,dp[0~9][k次操作],8加2呢是不是也是10,那么dp[8][2]=dp[9][1],那么这样子在不等于9的情况下,dp[i][j]=d[i+1][j-1],如果为9时,使得结果是由上面式子如何推出呢?,其实可以这样理解dp[9][j]=dp[10][j-1],而10又被分成了0和1,那么dp[9][j]=dp[1][j-1]+dp[0][j-1]。那么本体迎刃而解。

#include <bits/stdc++.h>
#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")
#pragma GCC optimization ("unroll-loops")
using namespace std;
#define ll long long
#define sl(n) scanf("%lld",&n)
#define pl(n) printf("%lld",n)
#define sdf(n) scanf("%lf",&n)
#define pdf(n) printf("%.lf",n)
#define pE printf("\n")
#define ull unsigned long long
#define pb push_back
#define debug(a) cout<<a<<"??"
#define me(a)  memset(a,0,sizeof(a))
#define pre(n) for(ll i=1;i<=n;i++)
#define rep(n) for(ll i=n;i>=1;i--)
#define ph push
#define pi pair<ll,ll>
#define fi first
#define se second
const ll mod = 1e9 + 7;
ll dp[11][200010], a[11];

void done()
{

    int i, j;
    for (i = 1; i <= 200010; i++)
    {
        for (j = 0; j < 9; j++)
        {
            dp[j][i] = dp[j + 1][i - 1] % mod;
        }
        dp[9][i] = (dp[9][i] + dp[1][i - 1] + dp[0][i - 1]) % mod;
    }
    return ;
}

void solve(ll k)

{

    ll ans = 0, i;

    for (i = 0; i <= 9; i++)
    {

        ans = (ans + a[i] * dp[i][k] % mod) % mod;

    }

    cout << ans << endl;

    return ;

}

int main()
{
    ll t, n, k;
    sl(t);
    for (int i = 0; i < 10; i++)dp[i][0] = 1;
    done();
    while (t--)
    {
        ll len = 0;
        sl(n), sl(k);
        me(a);
        while (n)
        {
            a[n % 10]++;
            n /= 10;
        }
        solve(k);
    }
    for (int i = 1; i <= 10; i++)
    {
        for (int j = 0; j <= 9; j++)cout << dp[j][i] << ' ';
        puts("");
    }
    return 0;
}

一维dp
当你分解出来的每一位数,如果加上k小于10那么位数就是1,如果位数如果大于10,你从dp[i+m-10]开始算起,每一位记录此时的下标从的0代表大于9的数能变出的位数,每多10位数发生变化,所以转移方程就是dp[i]=dp[i-10]+dp[i-9]

#include <bits/stdc++.h>
#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")
#pragma GCC optimization ("unroll-loops")
using namespace std;
#define ll long long
#define sl(n) scanf("%lld",&n)
#define pl(n) printf("%lld",n)
#define sdf(n) scanf("%lf",&n)
#define pdf(n) printf("%.lf",n)
#define pE printf("\n")
#define ull unsigned long long
#define pb push_back
#define debug(a) cout<<a<<"??"
#define me(a)  memset(a,0,sizeof(a))
#define pre(n) for(ll i=1;i<=n;i++)
#define rep(n) for(ll i=n;i>=1;i--)
#define ph push
#define pi pair<ll,ll>
#define fi first
#define se second
const ll mod = 1e9 + 7;
ll dp[200010];


int main()
{
    ll i, t, n, m, ans, cur;
    for (i = 0; i <= 8; i++)dp[i] = 2;
    dp[9] = 3;
    for (i = 10; i <= 200010; i++)
    {
        dp[i] = (dp[i - 9] + dp[i - 10]) % mod;
    }

    sl(t);

    while (t--)
    {
        sl(n), sl(m);

        ans = 0;

        while (n)
        {
            cur = n % 10;

            if (cur + m - 10 < 0) ans = (ans + 1) % mod;

            else ans = (ans + dp[cur + m - 10]) % mod;

            n /= 10;
        }
        cout << ans << endl;
    }
    return 0;
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值