zoukankan      html  css  js  c++  java
  • 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
    ", (cal(R+1)-cal(L)+mod)%mod );
    97     }
    98     return 0;
    99 }
    AC代码
  • 相关阅读:
    jsp 特殊标签
    poj 1753 Flip Game 高斯消元 异或方程组 求最值
    zoj 3155 Street Lamp 高斯消元 异或方程组 求方案数
    poj1222 EXTENDED LIGHTS OUT 高斯消元解异或方程组 模板
    zoj 3930 Dice Notation 模拟
    zoj 3157 Weapon 线段树求逆序对数
    hdu 1242 Rescue BFS+优先队列
    hdu 3466 Proud Merchants 贪心+01背包
    zoj 3689 Digging 贪心+01背包
    hdu 2602 Bone Collector 01背包模板
  • 原文地址:https://www.cnblogs.com/xcw0754/p/4853574.html
Copyright © 2011-2022 走看看