zoukankan      html  css  js  c++  java
  • HDU-4507

    HDU-4507

    题面

    单身!
      依然单身!
      吉哥依然单身!
      DS级码农吉哥依然单身!
      所以,他生平最恨情人节,不管是214还是77,他都讨厌!
      
      吉哥观察了214和77这两个数,发现:
      2+1+4=7
      7+7=72
      77=7
    11
      最终,他发现原来这一切归根到底都是因为和7有关!所以,他现在甚至讨厌一切和7有关的数!

      什么样的数和7有关呢?

      如果一个整数符合下面3个条件之一,那么我们就说这个整数和7有关——
      1、整数中某一位是7;
      2、整数的每一位加起来的和是7的整数倍;
      3、这个整数是7的整数倍;

      现在问题来了:吉哥想知道在一定区间内和7无关的数字的平方和。

    Input

    输入数据的第一行是case数T(1 <= T <= 50),然后接下来的T行表示T个case;每个case在一行内包含两个正整数L, R(1 <= L <= R <= 10^18)。

    Output

    请计算[L,R]中和7无关的数字的平方和,并将结果对10^9 + 7 求模后输出。

    Sample Input

    3
    1 9
    10 11
    17 17
    

    Sample Output

    236
    221
    0
    

    思路

    数位DP,我通过这篇博客学习

    与博客中普通的数位DP计数思路不同,本题需要求解所有数的平方和。

    由数位DP上一位推往这一位的列公式可得,上一位(x)这一位(y):

    (10*x+y)^2 = 100*x^2 + y^2 + 20*x*y ……公式1

    所以转移方程就变为:

    ans.cnt = ans.cnt + temp.cnt

    有cnt个数满足第pos位是i,所以有:

    ans.sum = temp.sum + i*len[pos]*temp.cnt

    所以由公式1可以得到:

    ans.sum2+=i*len[pos]*i*len[pos]*temp.cnt+temp.sqsum+2*i*len[pos]*temp.sum

    记得每次乘后要对题目要求的mod取余,否则数字过大会超过LL的范围

    记录sign1:所有位数和,sign2:该数

    存在dp数组中,方便下次搜索到该位且拥有相同的sign1和sign2时,可以直接返回结果。

    代码

    #include<iostream>
    #include<cstring>
    using namespace std;
    typedef long long ll;
    const ll mod = 1e9 + 7;
    int num[30];
    ll len[30];
    struct node {
        ll cnt;
        ll sum;   // 存数位累加和
        ll sqsum; // 存数位平方累加和
        node(int c=0, int s=0, int sq=0) : cnt(c), sum(s), sqsum(sq) {;}
    } dp[20][10][10];
    node dfs(int pos,int sign1, int sign2, bool limit) {
        // sign1 记录各个位和
        // sign2 记录该数和
        if(pos == -1) {
            node temp(0, 0, 0);
            if(sign1 && sign2) {
                temp.cnt = 1;
            }
            return temp;
        }
        if(!limit && dp[pos][sign1][sign2].cnt != -1) {
            return dp[pos][sign1][sign2];
        }
        int up = limit ? num[pos] : 9;
        node ans(0, 0, 0);
        for(int i=0;i<=up;i++) {
            if(i == 7) {
                continue;
            }
            node temp = dfs(pos-1, (sign1+i)%7, (sign2*10+i)%7, limit && num[pos] == i);
            ans.cnt = (ans.cnt + temp.cnt) % mod;
            // ans.sum = temp.sum + i*len[pos]*temp.cnt
            ans.sum=(ans.sum+(i*len[pos]%mod*temp.cnt%mod+temp.sum)%mod)%mod;
            // ans.sum2+=i*len[pos]*i*len[pos]*temp.cnt+temp.sqsum+2*i*len[pos]*temp.sum
            ans.sqsum=(ans.sqsum+(i*len[pos]%mod*i%mod*len[pos]%mod*temp.cnt%mod+temp.sqsum)%mod+2*i%mod*len[pos]%mod*temp.sum%mod)%mod;
        }
        if(!limit) {
            dp[pos][sign1][sign2] = ans;
        }
        return ans;
    }
    ll solve(ll x) { // 分解出各个位
        memset(dp, -1, sizeof(dp));
        int sign = 0;
        while(x) {
            num[sign++] = x % 10;
            x/=10; 
        }
        return dfs(sign-1, 0, 0, true).sqsum % mod;
    }
    int main() {
        len[0] = 1;
        for(int i=1;i<20;i++) {
            len[i] = len[i-1] * 10 % mod;
        }
        int n;
        cin >> n;
        while(n--) {
            ll l, r;
            cin >> l >> r;
            cout << ((solve(r) - solve(l-1)) % mod + mod) % mod << endl;
        }
    }
    
  • 相关阅读:
    Kafka-1
    消息队列
    分布式分类
    认识分布式
    数据库引擎
    Django插入多条数据—bulk_create
    Django中update和save()同时作用
    联合唯一去重的SQL
    Direct3D11学习:(三)Direct3D11初始化
    Direct3D11学习:(零)常见问题及解决方法整理
  • 原文地址:https://www.cnblogs.com/JoshuaYu/p/13603741.html
Copyright © 2011-2022 走看看