zoukankan      html  css  js  c++  java
  • hdu 4507 吉哥系列故事——恨7不成妻 [按位dp]

                 zzy 2013.3.22@科A232

     

      题目地址http://acm.hdu.edu.cn/showproblem.php?pid=4507 

      题目描述:求一个区间[L, R]中和7无关的数的平方和,和7无关的数定义为同时不满足下面三点:

      1.各位数字不包含7;

      2.各位数字之和不是7的倍数;

      3.这个整数不是7的倍数。

      解题思路:典型的按位dp。一开始想会不会是数学结论题,但是很快觉得数学一点不靠谱,然后发现按位dp可做。

      我的做法是求出区间[0, N]中满足条件的数的平方和,这样可以不用卡下界。

      定义数组dp[ d ][ u ][ i ][ j ],d表示dp到第d位,u表示是否卡上界(按惯例,0表示卡上界),i表示前缀的各位数字和模7为i,j表示前缀表示的整数模7为j。每个元素存num、sum、ssum三个值。num表示满足条件的前缀数量,sum则是这些前缀表示的整数的和,ssum是这些前缀表示的整数的平方和。

      dp从最高位到最低位枚举p,再枚举当前位的数字d,并枚举上一位p+1位的dp数组最后两维i:0~6,j:0~6。计算出转移到p位时的余数值:

      ii = (i + d)%7     jj = (j * 10 + d)%7

      最基本的转移方程是:

      dp[ p ][ 1 ][ ii ][ jj ].num += dp[ p + 1][ 1 ][ i ][ j ];

      dp[ p ][ 1 ][ ii ][ jj ].sum += dp[ p + 1 ][ 1 ][ i ][ j ].sum * 10 

            + dp[ p + 1 ][ 1 ][ i ][ j ].num * d;

      dp[ p ][ 1 ][ ii ][ jj ].ssum += dp[ p + 1 ][ 1 ][ i ][ j ].ssum * 100 

            + dp[ p + 1 ][ 1 ][ i ][ j ].sum * 20 * d 

            + d * d * dp[ p + 1 ][ 1 ][ i ][ j ].num;

    再注意考虑哈上界问题就行了。

     

    源代码

      1 //zzy.2013.3.21AC
      2 #include<cstdio>
      3 #include<iostream>
      4 #include<algorithm>
      5 
      6 using namespace std;
      7 
      8 #define ll long long
      9 #define MOD (1000000007LL)
     10 
     11 typedef struct
     12 {
     13     ll num,sum,ssum;
     14 }node;
     15 
     16 ll digits[21];
     17 node dp[21][2][7][7];
     18 
     19 void ini(ll len)
     20 {
     21     for(ll i = 1; i <= len + 1; ++i){
     22         for(ll j = 0; j < 2; ++j){
     23             for(ll k = 0; k < 7; ++k){
     24                 for(ll m = 0; m < 7; ++m){
     25                     dp[i][j][k][m].num = 0;
     26                     dp[i][j][k][m].sum = 0;
     27                     dp[i][j][k][m].ssum = 0;
     28                 }
     29             }
     30         }
     31     }
     32 }
     33 
     34 ll Len(ll N)
     35 {
     36     ll ret = 0;
     37     while(N){
     38         ret ++;
     39         digits[ret] = N % 10;
     40         N = N / 10;
     41     }
     42     return ret;
     43 }
     44 
     45 void DP(ll len)
     46 {
     47     for(ll p = len; p > 0; p--)
     48     {
     49         for(ll d = 0; d <= 9; d++)
     50         {
     51             if(d == 7) continue;
     52             for(ll i=0; i<7; i++)
     53             {
     54                 for(ll j=0; j<7; j++)
     55                 {
     56                     ll ii,jj;
     57                     ii = (i+d)%7;
     58                     jj = (j*10+d)%7;
     59                     dp[p][1][ii][jj].sum += dp[p+1][1][i][j].sum*10 
    + dp[p+1][1][i][j].num*d; 60 if(d < digits[p]) 61 dp[p][1][ii][jj].sum += dp[p+1][0][i][j].sum*10
    + dp[p+1][0][i][j].num*d; 62 dp[p][1][ii][jj].sum %= MOD; 63 64 dp[p][1][ii][jj].num += dp[p+1][1][i][j].num; 65 if(d < digits[p]) 66 dp[p][1][ii][jj].num += dp[p+1][0][i][j].num; 67 dp[p][1][ii][jj].num %= MOD; 68 69 dp[p][1][ii][jj].ssum += dp[p+1][1][i][j].ssum * 100LL
    + 20LL * d * dp[p+1][1][i][j].sum + d*d * dp[p+1][1][i][j].num; 70 if(d < digits[p]) 71 dp[p][1][ii][jj].ssum += dp[p+1][0][i][j].ssum * 100LL
    + 20LL * d * dp[p+1][0][i][j].sum + d*d * dp[p+1][0][i][j].num; 72 dp[p][1][ii][jj].ssum %= MOD; 73 } 74 } 75 } 76 ll d = digits[p]; 77 if(d == 7) continue; 78 for(ll i=0; i<7; i++) 79 { 80 for(ll j=0; j<7; j++)if(dp[p+1][0][i][j].num) 81 { 82 ll ii,jj; 83 ii = (i+d)%7; 84 jj = (j*10+d)%7; 85 dp[p][0][ii][jj].sum += dp[p+1][0][i][j].sum*10 + dp[p+1][0][i][j].num*d; 86 dp[p][0][ii][jj].sum %= MOD; 87 88 dp[p][0][ii][jj].num += dp[p+1][0][i][j].num; 89 dp[p][0][ii][jj].num %= MOD; 90 91 dp[p][0][ii][jj].ssum += dp[p+1][0][i][j].ssum * 100LL
    + 20LL * d * dp[p+1][0][i][j].sum + d*d * dp[p+1][0][i][j].num; 92 dp[p][0][ii][jj].ssum %= MOD; 93 } 94 } 95 } 96 } 97 98 ll calcu(ll N) 99 { 100 ll len = Len(N); 101 ini(len); 102 dp[len+1][0][0][0].num = 1; 103 DP(len); 104 ll ret = 0; 105 for(ll i=1; i<7; i++){ 106 for(ll j=1; j<7; j++){ 107 ret += dp[1][0][i][j].ssum; 108 ret += dp[1][1][i][j].ssum; 109 } 110 } 111 ret %= MOD; 112 return ret; 113 } 114 115 int main() 116 { 117 ll T; 118 cin >> T; 119 while(T--){ 120 ll A,B; 121 cin >> A >> B; 122 ll ans = 0; 123 ans = calcu(B) - calcu(A - 1); 124 ans = (ans + MOD) % MOD; 125 cout << ans << endl; 126 } 127 return 0; 128 }

     

     

     

  • 相关阅读:
    LINQ/EF/Lambda 比较字符串日期时间大小
    WinForm RDLC SubReport Step by step
    centos7安装7-zip
    centos修改命令提示符颜色
    更换官方zabbix.repo为阿里云镜像
    利用shell脚本清理nginx日志
    docker
    centos 建立静态 IP 与 IP 地址丢失的解决办法
    构建lnmp高可用架构
    keepalived高可用
  • 原文地址:https://www.cnblogs.com/Lattexiaoyu/p/2974669.html
Copyright © 2011-2022 走看看