计蒜客 - 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]; }