HDU 4507 有点复杂却不难的数位DP

首先来说,,这题我wrong了好几次,代码力太弱啊。。很多细节没考虑。。

题意:给定两个数 L R,1 <= L <= R <= 10^18 ;求L 到 R 间 与 7 无关的数的平方和

什么数与7 无关?

1 没有数字7

2 不是7的倍数

3 所有数字的和不是7的倍数

我们先来考虑一下  如果这题问的是: L 到 R 间 与7 无关的数有多少个?

这道题该怎么思考? 给一点提示  dp 方程可以写成三维的 num(i,j,k) 其中 i 代表数的位数 j 代表 这个数对7取模的余数 k 代表这个数所有数字和对7取模的值,至于num(i,j,k) 当让就是这种数的个数了, 方程的转化也很简单  从数末尾逐步填数字 l (0~9)的话 num(i+1,(j*10+l)%7,(k+l)%7)+=num(i,j,k);

接下来 我默认你知道 num[i][j][k] 该怎么求了 这个时候 再来考虑一下 L 到 R 间与7 无关的数的和 ? 这个时候不用考虑的太复杂,,因为首先,你在求num[i][j][k]的时候已经求出了所有的满足条件的数的所有可能,要求和,无非就是哪一位的那个数字有多少个。

如果我们的dp是逐步往数的末尾填数 ,这个时候可以这样写 sum(i,j,k)其中i,j,k和num的i,j,k一个意思,然后sum表示满足这种情况的数的和 方程的转换可以写为:同样从数末尾逐步填数字 l (0~9)-- num(i+1,(j*10+l)%7,(k+l)%7)+=sum(i,j,k)*10+num(i,j,k)*l;

再来考虑平方和就比较容易了,,我们知道如果前面的数是a 我们往后面塞一个数字l 那么我们要求的数的平方和是---(10*a+l)^2 也就是100*a*a+20*a*l+l*l

方程我就不写了,,然后接下来的思路都是和上面的类似

贴出渣渣的代码。。。

  1 #include<iostream>
  2 #include<stdio.h>
  3 #include<string.h>
  4 #include <string>
  5 #include <cmath>
  6 #include <algorithm>
  7 #include <map>
  8 #include <set>
  9 #include <queue>
 10 #include <stack>
 11 #include<stdlib.h>
 12 #include <vector>
 13 using namespace std;
 14 #pragma comment(linker, "/STACK:1024000000,1024000000")
 15 #define ll __int64
 16 #define CL(a,b) memset(a,b,sizeof(a))
 17 #define MAXNODE 100010
 18 ll MOD=1000000007;
 19
 20 ll s,e;
 21
 22 ll dp[30][7][7];
 23 ll wsu[30][7][7];
 24 ll num[30][7][7];
 25 ll val[30];
 26 void initval()
 27 {
 28     int i=0;
 29     val[1]=1;
 30     val[0]=0;
 31     for(i=2;i<=19;i++)
 32     {
 33         val[i]=val[i-1]*10;
 34     }
 35 }
 36
 37 void initdp()
 38 {
 39     int i,j,k,l;
 40     CL(dp,0);
 41     CL(num,0);
 42     CL(wsu,0);
 43     for(i=0;i<10;i++)
 44     {
 45         if(i==7)continue;
 46         dp[1][i%7][i%7]+=i*i;
 47         wsu[1][i%7][i%7]+=i;
 48         num[1][i%7][i%7]++;
 49     }
 50     num[0][0][0]=1;
 51     for(i=1;i<29;i++)
 52     {
 53         for(j=0;j<7;j++)
 54         {
 55             for(k=0;k<7;k++)
 56             {
 57                 for(l=0;l<10;l++)
 58                 {
 59                     if(l==7)continue;
 60                     num[i+1][(j+l)%7][(k*10+l)%7]+=num[i][j][k]%MOD;
 61                     num[i+1][(j+l)%7][(k*10+l)%7]%=MOD;
 62                     wsu[i+1][(j+l)%7][(k*10+l)%7]+=(wsu[i][j][k]*(ll)10+(ll)l*(num[i][j][k]))%MOD;
 63                     wsu[i+1][(j+l)%7][(k*10+l)%7]%=MOD;
 64                     dp[i+1][(j+l)%7][(k*10+l)%7]+=(((ll)l*(ll)l*num[i][j][k])+dp[i][j][k]*100+(ll)2*(ll)l*wsu[i][j][k]*(ll)10)%MOD;
 65                     dp[i+1][(j+l)%7][(k*10+l)%7]%=MOD;
 66                 }
 67  //               printf("%d %d %d %I64d\n",i,j,k,dp[i][j][k]);
 68             }
 69         }
 70     }
 71 }
 72
 73 ll pro(ll n)
 74 {
 75     if(n==0)return 0;
 76     ll rem=0;
 77     ll nu[30];
 78     int w,i,j,k;
 79     nu[0]=0;
 80     ll tem=n,va;w=1,rem=0;
 81     while(tem!=0)
 82     {
 83         nu[w]=tem%10;
 84         tem/=10;
 85         w++;
 86     }
 87     va=0;
 88     int su=0;
 89     ll v=0;
 90     while(--w)
 91     {
 92         if(nu[w]==7)
 93         {
 94             for(i=1;i<w;i++)nu[i]=9;
 95             nu[w]=6;
 96         }
 97         for(i=nu[w]-1;i>=0;i--)
 98         {
 99             if(i==7)continue;
100             for(j=0;j<7;j++)
101             {
102                 for(k=0;k<7;k++)
103                 {
104                     if((su+i+j)%7==0)continue;
105                     if(((ll)v+(ll)i*val[w]+(ll)k)%7==0)continue;
106                     ll pre=(va+(ll)i*(val[w]%MOD))%MOD;
107                     pre%=MOD;
108                     rem+=(((pre*pre)%MOD)*(num[w-1][j][k]%MOD))%MOD;
109                     rem%=MOD;
110                     rem+=dp[w-1][j][k]%MOD;;
111                     rem%=MOD;
112                     rem+=((((ll)2*pre)%MOD)*wsu[w-1][j][k]%MOD)%MOD;
113                     rem%=MOD;
114                 }
115             }
116         }
117         rem%=MOD;
118         va+=(nu[w]*(val[w]%MOD))%MOD;
119         va%=MOD;
120         v+=nu[w]*(val[w]%7);
121         v%=7;
122         su+=nu[w];
123         su%=7;
124     }
125     if(v!=0&&su!=0)rem+=(va*va)%MOD;
126     return rem%MOD;
127 }
128
129 int main()
130 {
131     int tt;
132     initval();
133     initdp();
134     scanf("%d",&tt);
135     while(tt--)
136     {
137         scanf("%I64d %I64d",&s,&e);
138         ll rs=pro(s-1LL);
139         ll re=pro(e);
140         ll rem=re-rs;
141         rem=rem%MOD;
142         if(rem<0)rem+=MOD;
143  //       printf("%I64d %I64d ",rs,re);
144         printf("%I64d\n",rem);
145     }
146     return 0;
147 }
时间: 2024-10-10 22:18:13

HDU 4507 有点复杂却不难的数位DP的相关文章

【HDU 4352】 XHXJ&#39;s LIS (数位DP+状态压缩+LIS)

XHXJ's LIS Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2422    Accepted Submission(s): 990 Problem Description #define xhxj (Xin Hang senior sister(学姐)) If you do not know xhxj, then careful

HDU 4389 X mod f(x) (数位DP)

题目链接  HDU4389 题意  给出T个区间[L, R],统计L到R中有多少个满足条件的数. 限制条件为该数能被这个数的各位数字之和整除. 数据范围$1 <= L <= R <= 10^{9}$ 考虑数位DP 注意到f(x)最大为81,所以对1-81每一个和做一遍数位DP即可. f[pos][mod][sum][x] 表示当前处理到第pos位,当前的数位和对x取模的结果,当前的数位和,以及当前正在求的x = f(x) #include <bits/stdc++.h> us

HDU 4389——X mod f(x)(数位DP)

X mod f(x) Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Problem Description Here is a function f(x): int f ( int x ) {     if ( x == 0 ) return 0;     return f ( x / 10 ) + x % 10; } Now, you want to know, in a 

hdu 3709 Balanced Number(平衡数)--数位dp

Balanced Number Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)Total Submission(s): 9036    Accepted Submission(s): 4294 Problem Description A balanced number is a non-negative integer that can be balanced if a pi

hdu 2089 不要62 【数位DP】

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2089 数位DP模板题,测试板子 代码: #include <stdio.h> #include <ctime> #include <math.h> #include <limits.h> #include <complex> #include <string> #include <functional> #include &l

浅谈数位DP

在了解数位dp之前,先来看一个问题: 例1.求a~b中不包含49的数的个数. 0 < a.b < 2*10^9 注意到n的数据范围非常大,暴力求解是不可能的,考虑dp,如果直接记录下数字,数组会开不起,该怎么办呢?要用到数位dp. 数位dp一般应用于: 求出在给定区间[A,B]内,符合条件P(i)的数i的个数. 条件P(i)一般与数的大小无关,而与 数的组成 有关. 这样,我们就要考虑一些特殊的记录方法来做这道题.一般来说,要保存给定数的每个位置的数.然后要记录的状态为当前操作数的位数,剩下的

HDU 4507 (鬼畜级别的数位DP)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4507 题目大意:求指定范围内与7不沾边的所有数的平方和.结果要mod 10^9+7(鬼畜の元凶) 解题思路: 与7不沾边的数需要满足三个条件. ①不出现7 ②各位数和不是7的倍数 ③这个数不是7的倍数 这三个条件都是基础的数位DP. 但是这题要统计的不是符合条件个数,而是平方和. 也就是说在DP时候,要重建每个数,算出平方,然后求和. 需要维护三个值(推荐使用结构体), 假定dfs推出返回的结构体是

Hdu 4507 吉哥系列故事——恨7不成妻 (数位DP)

题目链接: Hdu 4507 吉哥系列故事——恨7不成妻 题目描述: 中文题面不描述. 解题思路: 从数据范围可看出是数位DP.根据题目给的限制,如果是求满足限制的数的数目的话,就很简单了.但是这个题目是让求满足题目中限制的数的平方和.我们可以求出区间中满足题目中限制的数的数目,和这些数的和,然后从这两个东西推出这些数的平方和. 假设现在我们已经递归出后面的x-1位满足题目限制的数的数目(num),和(sum),平方和(ssum),当前x位枚举为i,就可以推出当前节点改变为Num += num,

hdu 4507 数位dp(求和,求平方和)

http://acm.hdu.edu.cn/showproblem.php?pid=4507 Problem Description 单身! 依然单身! 吉哥依然单身! DS级码农吉哥依然单身! 所以,他生平最恨情人节,不管是214还是77,他都讨厌! 吉哥观察了214和77这两个数,发现: 2+1+4=7 7+7=7*2 77=7*11 最终,他发现原来这一切归根到底都是因为和7有关!所以,他现在甚至讨厌一切和7有关的数! 什么样的数和7有关呢? 如果一个整数符合下面3个条件之一,那么我们就说