zoukankan      html  css  js  c++  java
  • HDU4507.吉哥系列故事——恨7不成妻(数位DP)

    HDU4507

    如果一个整数符合下面3个条件之一,那么我们就说这个整数和7有关——

    1、整数中某一位是7。

    2、整数中的每一位加起来的和是7的整数倍。

    3、这个整数是7的整数倍。

    要求一个区间中和7无关的数的平方和。

    需要用数位DP维护3个值:

    1、与7无关的数的个数。

    2、与7无关的数的和。

    3、与7无关的数的平方和。

     

    #include<bits/stdc++.h>
    using namespace std;
    const int mod=1e9+7;
    struct node {
        long long cnt;//与7无关的数的个数 
        long long sum;//与7无关的数的和 
        long long sqsum;//平方和 
    }f[20][20][20];//分别是处理的数位、数字和%7、数%7
    int bit[20];
    long long p[20];//p[i]=10^i
    node dfs (int pos,int pre1,int pre2,bool flag) {
        if (pos==-1) {
            node tt;
            tt.cnt=(pre1!=0&&pre2!=0);
            tt.sum=tt.sqsum=0;
            return tt;
        }
        if (!flag&&f[pos][pre1][pre2].cnt!=-1) {
            return f[pos][pre1][pre2];
        }
        int ed=flag?bit[pos]:9;
        node ans,tt;
        ans.cnt=ans.sqsum=ans.sum=0;
        for (int i=0;i<=ed;i++) {
            if (i==7) continue;
            tt=dfs(pos-1,(pre1+i)%7,(pre2*10+i)%7,flag&&i==ed);
            ans.cnt+=tt.cnt;
            ans.cnt%=mod;
            
            ans.sum+=(tt.sum+((p[pos]*i)%mod)*tt.cnt%mod)%mod;
            ans.sum%=mod;
            
            ans.sqsum+=(tt.sqsum+((2*p[pos]*i)%mod)*tt.sum)%mod;
            ans.sqsum%=mod;
            
            ans.sqsum+=((tt.cnt*p[pos])%mod*p[pos]%mod*i*i%mod);
            ans.sqsum%=mod;
        }
        if (!flag) f[pos][pre1][pre2]=ans;
        return ans; 
    }
    long long calc (long long n) {
        int pos=0;
        while (n) {
            bit[pos++]=n%10;
            n/=10;
        }
        return dfs(pos-1,0,0,1).sqsum;
    }
    int main () {
        p[0]=1;
        for (int i=1;i<20;i++) {
            p[i]=p[i-1]*10;
            p[i]%=mod;
        }
        for (int i=0;i<20;i++) {
            for (int j=0;j<20;j++) {
                for (int k=0;k<20;k++) {
                    f[i][j][k].cnt=-1;
                }
            }
        }
        int _;
        scanf("%d",&_);
        while (_--) {
            long long n,m;
            scanf("%lld%lld",&n,&m);
            long long ans=calc(m)-calc(n-1);
            ans=(ans+mod)%mod;
            printf("%lld
    ",ans);
        }
    }
  • 相关阅读:
    由优化反射性能问题引发的思考
    Flash还能走多远?
    .net CLR 4.0垃圾回收机制的改进之3
    Silverlight 3引入了GPU加速的特性
    java 字符串
    JAVA 容器
    JAVA 反转链表
    JAVA 自定义比较器
    JAVA 类相关知识
    vscode 输出中文乱码
  • 原文地址:https://www.cnblogs.com/zhanglichen/p/14395815.html
Copyright © 2011-2022 走看看