HDU 4507 吉哥系列故事——恨7不成妻 (数位DP)
2015-10-03 16:54
357 查看
题意:
如果一个整数符合下面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。
AC代码
如果一个整数符合下面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。
#include <bits/stdc++.h> #define pii pair<int,int> #define INF 0x7f3f3f3f #define LL long long #define ULL unsigned long long using namespace std; const double PI = acos(-1.0); const int N=19; const LL mod=1e9+7; struct node { /* 1.与7无关的数的个数 2.与7无关的数的和 3.与7无关的数的平方和。 */ ULL cnt; ULL sum; ULL ssum; }dp [7][7]; void pre_cal() { ULL base=dp[0][0][0].cnt=1; for(int i=1; i<N; i++,base*=10 ) //位数 { for(int u=0; u<10; u++) //第i位为u { if(u==7) continue; //不合法 ULL c=u*base%mod; for(int j=0; j<7; j++) //位和 for(int k=0; k<7; k++) //数和 { ULL a=(u+j)%7, b=(u*base+k)%7; ULL sum =dp[i-1][j][k].sum,ssum=dp[i-1][j][k].ssum,cnt =dp[i-1][j][k].cnt;; dp[i][a][b].cnt +=cnt; //个数 dp[i][a][b].cnt %=mod; dp[i][a][b].sum +=sum +c*cnt%mod; //和 dp[i][a][b].sum %=mod; dp[i][a][b].ssum+=ssum + 2*c*sum%mod + cnt*c%mod*c%mod;//平方和:3部分 dp[i][a][b].ssum%=mod; } } } } int bit[N+2]; ULL cal(ULL n) { memset(bit, 0, sizeof(bit)); ULL base=1, ans=0, len=0, i, pre=0, bsum=0; //bsum记录前缀的位和 while(n) { bit[++len]=n%10; n/=10; base*=10; } for( i=len; i>0; i--) { base/=10; for(int u=0; u<bit[i]; u++) //当前位 { if(u==7) continue; ULL c=(pre*10+u)*base%mod; //前缀,注意c已经取模了 for(int a=0; a<7; a++) //位和 for(int b=0; b<7; b++) //数和 if( (bsum+u+a)%7 && ( (pre*10%7+u)*base+b)%7 ) { ULL cnt=dp[i-1][a][b].cnt; ULL sum=dp[i-1][a][b].sum; ULL ssum=dp[i-1][a][b].ssum; ans+= ssum + 2*c*sum%mod + cnt*c%mod*c%mod ; ans%=mod; } } pre=pre*10+bit[i]; bsum+=bit[i]; //前缀的位和 if(bit[i]==7) break; //前缀出现了7,后面不可能了 } return ans%mod; } int main() { //freopen("input.txt","r",stdin); pre_cal(); LL L, R; int t;cin>>t; while(t--) { scanf("%lld %lld",&L,&R); printf("%llu\n", (cal(R+1)-cal(L)+mod)%mod ); } return 0; }
AC代码
相关文章推荐
- Android API在不同版本系统上的兼容性
- POJ 2325
- Spring 初始化Init和销毁Destory:
- Arduino1:中断知识点汇总
- ffplay for mfc 代码备忘录
- Linux Shell学习笔记3:更多的bash shell命令
- hadoop2.7.1伪分布模式配置文件
- AutoCompleteTextView学习
- greenDao框架使用心得
- 苹果开发 笔记(83)CABasicAnimation
- 项目32.3 输出小星星
- 音频播放AVAudioPlayer
- 使用IntelliJ IDEA开发SpringMVC网站(二)框架配置
- ok6410 2g NandFalsh 256ram tftp挂载zImage
- android stdio下的项目目录结构简介
- hdu 5479 Scaena Felix 枚举
- php curl_multi批量发送http请求
- Spring 容器创建bean的scope
- MS12-020蓝屏攻击
- 住javaWeb分页实现(模拟百度首页)