zoukankan      html  css  js  c++  java
  • [洛谷P4999]烦人的数学作业

    题目大意:定义$f(x)$表示$x$每一个数位(十进制)的数之和,求$sumlimits_{i=l}^rf(i)$,多组询问。

    题解:数位$DP$,可以求出每个数字的出现个数,再乘上每个数字的大小即可。

    卡点:无(结构体记得写构造函数清空)

    C++ Code:

    #include <algorithm>
    #include <cstdio>
    #define maxn 20
    const int mod = 1e9 + 7;
    inline void reduce(int &x) { x += x >> 31 & mod; }
    inline int getreduce(int x) { return x + (x >> 31 & mod); }
    
    int Tim;
    struct node {
    	int s[10], cnt;
    	inline node() { __builtin_memset(s, 0, 10 << 2); cnt = 0; }
    	inline void operator += (const node &rhs) {
    		for (int i = 0; i < 10; ++i) reduce(s[i] += rhs.s[i] - mod);
    		reduce(cnt += rhs.cnt - mod);
    	}
    	inline int get() {
    		int res = 0;
    		for (int i = 1; i < 10; ++i) reduce(res += static_cast<long long> (s[i]) * i % mod - mod);
    		return res;
    	}
    } F[maxn], I;
    bool vis[maxn];
    
    int num[maxn], tot;
    node calc(int x, bool lim, bool lead) {
    	if (!x) return I;
    	if (!lim && lead && vis[x]) return F[x];
    	node f;
    	for (int i = lim ? num[x] : 9, op = 1; ~i; --i, op = 0) {
    		node val = calc(x - 1, lim && op, lead || i);
    		f += val;
    		if (i || lead) reduce(f.s[i] += val.cnt - mod);
    	}
    	if (!lim && lead) F[x] = f, vis[x] = true;
    	return f;
    }
    int solve(long long x) {
    	if (x < 0) return 0;
    	tot = 0;
    	while (x) {
    		num[++tot] = x % 10;
    		x /= 10;
    	}
    	return calc(tot, true, false).get();
    }
    
    int main() {
    	scanf("%d", &Tim);
    	I.cnt = 1;
    	while (Tim --> 0) {
    		long long l, r;
    		scanf("%lld%lld", &l, &r);
    		printf("%d
    ", getreduce(solve(r) - solve(l - 1)));
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    Python与Flask
    Python与MySQL
    range,map,sum
    Java:初始化类、变量、程序块加载解析
    HTML_记录2
    HTML_记录1
    查看当前连接的实例名
    expdp impdp
    行列转换
    oracle创建定时任务
  • 原文地址:https://www.cnblogs.com/Memory-of-winter/p/10331386.html
Copyright © 2011-2022 走看看