计蒜客 - 45276 D - number

 思路:这数据远远超过2^64,所以求答案时一定时高精度去算,我这里用了自己的高精度减减法模板和高精度乘低精度乘法模板,有兴趣可以深入理解里面的每一个意思。

  算3的个数时不难,当n=1,ans1=1(10里面只有3),当n=2,ans2=19(100里有3.13.23.30.31...83.93)当n=3,ans3=271,其实你可以考虑,每当你+一个10你就会多出一个3(当然30几,300几那些多出10个多100个)

仔细想想其实一个很简单的dp方程 

 1 int dp[N][3];//0表示在个位数有多少,1表示十位数以上有多少
 2 void init()
 3 {
 4     dp[0][0] = 1;
 5     dp[0][1] = 1;
 6     for (int i = 1; i <= 1003; i++)
 7     {
 8         dp[i][0] = dp[i - 1][0]*9;
 9         dp[i][1] = (dp[i - 1][1]*10 + dp[i][0]);
10     }
11 }

但是,显然这样做也不是,毕竟1000次方,还是要高精度,所以得换个思路,其实ans1=10-9,ans2=100-81,ans3=1000-729,用数学归纳法就是ansn=pow(10,n)-pow(9,n),当然不能用快速,数据就1000,老老实实暴力算出来吧!

代码

#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#define ll long long 
using namespace std;
const int N = 1005;
const int mod = 10007;
vector<int> sub(vector<int>& A, vector<int>& B)
{
    vector<int>C;
    for (int i = 0, t = 0; i < A.size(); i++)
    {
        t = A[i] - t;
        if (i < B.size())t -= B[i];
        C.push_back((t + 10) % 10);
        if (t < 0)t = 1;
        else t = 0;
    }
    while (C.size() > 1 && C.back() == 0)C.pop_back();
    return C;
}
vector<int> mul(vector<int>& A, int b)
{
    vector<int>C;
    int t = 0;
    for (int i = 0; i < A.size() || t; i++)
    {
        if (i < A.size())t += A[i] * b;
        C.push_back(t % 10);
        t /= 10;
    }
    while (C.size() > 1 && C.back() == 0)C.pop_back();
    return C;
}
int main()
{
    freopen("number.in", "r", stdin);
    freopen("number.out", "w", stdout);
    vector<int>A, B,H;
    ll n, c;
    cin >> n;
    int b = 9;
    H.push_back(1);
    for (int i = 0; i < n; i++)
    {
        H = mul(H, b);
    }
    for (int i = 0; i < n; i++)A.push_back(0);
    A.push_back(1);
    auto C = sub(A, H);
    for (int i = C.size() - 1; i >= 0; i--)cout << C[i];

}

猜你喜欢

转载自www.cnblogs.com/ch-hui/p/12940136.html