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

题意:

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

  给定一个区间[L,R],问在此区间内和7无关的所有数字的平方和。

思路:

  第一步好解决,只是数位DP的基础。第二步是十进制的所有位加起来是7的整数倍,这个只是需要用多一维来记录%7的结果就行了。第三步是7的整数倍问题,假设c=a+b,那么c%7=(a%7+b)%7,就假设这个数是10086,那么(10000%7+86)%7就行了,一样可以通过增加一维来解决。最后还要解决平方和问题,如第三步,(a+b)2=a2+2ab+b2,而∑(b2)部分已经在前面完成了,我们需要将其记录起来。剩下a2+2ab需要解决,∑(a2)直接算,∑(2ab)=2a*∑(b),所以∑(b)也是需要记录的,而求和∑就需要知道前面到底有几个数是合法的才行,则需要记录个数cnt。所以一共需要用到3维的数组,其中需要记录合法个数cnt,数的和sum,数的平方和ssum。

 1 #include <bits/stdc++.h>
 2 #define pii pair<int,int>
 3 #define INF 0x7f3f3f3f
 4 #define LL long long
 5 #define ULL unsigned long long
 6 using namespace std;
 7 const double PI  = acos(-1.0);
 8 const int N=19;
 9 const LL mod=1e9+7;
10
11 struct node
12 {
13 /*
14     1.与7无关的数的个数
15     2.与7无关的数的和
16     3.与7无关的数的平方和。
17 */
18     ULL  cnt;
19     ULL  sum;
20     ULL  ssum;
21 }dp[N][7][7];
22
23 void pre_cal()
24 {
25     ULL base=dp[0][0][0].cnt=1;
26     for(int i=1; i<N; i++,base*=10 ) //位数
27     {
28         for(int u=0; u<10; u++) //第i位为u
29         {
30             if(u==7)    continue;   //不合法
31             ULL c=u*base%mod;
32
33             for(int j=0; j<7; j++)  //位和
34             for(int k=0; k<7; k++)  //数和
35             {
36                 ULL a=(u+j)%7, b=(u*base+k)%7;
37                 ULL sum =dp[i-1][j][k].sum,ssum=dp[i-1][j][k].ssum,cnt =dp[i-1][j][k].cnt;;
38
39                 dp[i][a][b].cnt +=cnt;                              //个数
40                 dp[i][a][b].cnt %=mod;
41                 dp[i][a][b].sum +=sum +c*cnt%mod;                   //和
42                 dp[i][a][b].sum %=mod;
43                 dp[i][a][b].ssum+=ssum + 2*c*sum%mod + cnt*c%mod*c%mod;//平方和:3部分
44                 dp[i][a][b].ssum%=mod;
45             }
46         }
47     }
48 }
49
50 int bit[N+2];
51 ULL cal(ULL n)
52 {
53     memset(bit, 0, sizeof(bit));
54     ULL base=1, ans=0, len=0, i, pre=0, bsum=0; //bsum记录前缀的位和
55     while(n)
56     {
57         bit[++len]=n%10;
58         n/=10;
59         base*=10;
60     }
61     for( i=len; i>0; i--)
62     {
63         base/=10;
64         for(int u=0; u<bit[i]; u++)     //当前位
65         {
66             if(u==7) continue;
67             ULL c=(pre*10+u)*base%mod;  //前缀,注意c已经取模了
68             for(int a=0; a<7; a++)      //位和
69                 for(int b=0; b<7; b++)  //数和
70                     if( (bsum+u+a)%7 && ( (pre*10%7+u)*base+b)%7 )
71                     {
72                         ULL cnt=dp[i-1][a][b].cnt;
73                         ULL sum=dp[i-1][a][b].sum;
74                         ULL ssum=dp[i-1][a][b].ssum;
75
76                         ans+= ssum + 2*c*sum%mod + cnt*c%mod*c%mod ;
77                         ans%=mod;
78                     }
79         }
80         pre=pre*10+bit[i];
81         bsum+=bit[i];   //前缀的位和
82         if(bit[i]==7)   break;  //前缀出现了7,后面不可能了
83     }
84     return ans%mod;
85 }
86
87 int main()
88 {
89     //freopen("input.txt","r",stdin);
90     pre_cal();
91     LL L, R;
92     int t;cin>>t;
93     while(t--)
94     {
95         scanf("%lld %lld",&L,&R);
96         printf("%llu\n", (cal(R+1)-cal(L)+mod)%mod );
97     }
98     return 0;
99 }

AC代码

时间: 2024-09-30 16:19:12

HDU 4507 吉哥系列故事——恨7不成妻 (数位DP)的相关文章

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

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

HDU 4507 吉哥系列故事――恨7不成妻(数位dp&amp;好魔性的一道好题)

题目链接:[kuangbin带你飞]专题十五 数位DP J - 吉哥系列故事――恨7不成妻 题意 Time Limit:500MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Description 单身! 依然单身! 吉哥依然单身! DS级码农吉哥依然单身! 所以,他生平最恨情人节,不管是214还是77,他都讨厌! 吉哥观察了214和77这两个数,发现: 2+1+4=7 7+7=7*2 77=7*11 最终,他发现原来这一切归根到底都是

hdu 4507 吉哥系列故事――恨7不成妻 数位dp

题意:中文题. 思路:设dp[pos][i][j]表示当前考虑pos位,之前的数位和对7的余数为i,之前的数值对7的余数为j,与之后的(pos+1)位组合满足条件 的状态(包括之后(pos+1)位满足的个数,后缀和sum,后缀平方和),详见代码: /********************************************************* file name: hdu4507.cpp author : kereo create time: 2015年02月10日 星期二

HDU ACM 4507 吉哥系列故事——恨7不成妻 -&gt;数位DP

题意:如果一个整数符合下面3个条件之一,那么我们就说这个整数和7有关-- 1.整数中某一位是7: 2.整数的每一位加起来的和是7的整数倍: 3.这个整数是7的整数倍: 现在问题来了:吉哥想知道在一定区间内和7无关的数字的平方和. 分析:数位DP,关键内容如下. (pre0+i)%7用于处理各个位数之和时候为7的倍数,(pre1*10+i)%7用于处理这个数是否为7的倍数. #include<iostream> using namespace std; const __int64 mod=100

HDU - 4507 吉哥系列故事――恨7不成妻 (数位DP)

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

HDU 4507 —— 吉哥系列故事――恨7不成妻

吉哥系列故事――恨7不成妻 Time Limit:500MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Description 单身!  依然单身!  吉哥依然单身!  DS级码农吉哥依然单身!  所以,他生平最恨情人节,不管是214还是77,他都讨厌!    吉哥观察了214和77这两个数,发现:  2+1+4=7  7+7=7*2  77=7*11  最终,他发现原来这一切归根到底都是因为和7有关!所以,他现在甚至讨

HDU - 4507 - 吉哥系列故事——恨7不成妻(数位DP,数学)

链接: https://vjudge.net/problem/HDU-4507 题意: 单身! 依然单身! 吉哥依然单身! DS级码农吉哥依然单身! 所以,他生平最恨情人节,不管是214还是77,他都讨厌! 吉哥观察了214和77这两个数,发现: 2+1+4=7 7+7=72 77=711 最终,他发现原来这一切归根到底都是因为和7有关!所以,他现在甚至讨厌一切和7有关的数! 什么样的数和7有关呢? 如果一个整数符合下面3个条件之一,那么我们就说这个整数和7有关-- 1.整数中某一位是7: 2.

hdu-4507 吉哥系列故事——恨7不成妻 数位DP 状态转移分析/极限取模

http://acm.hdu.edu.cn/showproblem.php?pid=4507 求[L,R]中不满足任意条件的数的平方和mod 1e9+7. 条件: 1.整数中某一位是7:2.整数的每一位加起来的和是7的整数倍:3.这个整数是7的整数倍: 首先想到数位DP,我们看下如何维护. 最基本的dp需要两维来维护起始数字和长度,此外对于数位求和mod 7的余数需要一维来维护,对于一个数mod 7的余数需要一维维护. 此外我们处理一下平方和,对于一个x开头,长度为len的xoo型数集,把它分成

HDU 4507 吉哥系列故事――恨7不成妻(数位DP+结构体)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4507 题目大意:如果一个整数符合下面3个条件之一,那么我们就说这个整数和7有关 1.整数中某一位是7: 2.整数的每一位加起来的和是7的整数倍: 3.这个整数是7的整数倍: 求一定区间内和7无关的数字的平方和. 解题思路:这里我们用一个结构体分别存储符合条件的数的个数n,从当前位开始至末尾的数值s(比如一个数当前为1234***,*表示还不知道的位值,代表的就是***),从当前位开始至末尾的数的平方

HDU 4507 吉哥系列故事——恨7不成妻

需要推下平方和的式子..维护个数,和,平方和. #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define mod 1000000007LL using namespace std; long long bit[30],tab[50],ret=0,t,l,r; struct pnt { long long val1,val2,val3; pnt (long