寒假Day30:HDU4507吉哥系列故事恨7不成妻数位dp

题面:

单身!
  依然单身!
  吉哥依然单身!
  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的整数倍;

  现在问题来了:吉哥想知道在一定区间内和7无关的数字的平方和。
Input
输入数据的第一行是case数T(1 <= T <= 50),然后接下来的T行表示T个case;每个case在一行内包含两个正整数L, R(1 <= L <= R <= 10^18)。
Output
请计算[L,R]中和7无关的数字的平方和,并将结果对10^9 + 7 求模后输出。
Sample Input
3
1 9
10 11
17 17
Sample Output
236
221
0
View Code

题意:

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

  求给定区间内和7无关的数字的平方和。

https://blog.csdn.net/Estia_/article/details/83479031

这个博客的思路写的清楚倒挺好的,但是这个代码里面的结构体里面的结构体我没看懂,,

代码:

#include<string.h>
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;

struct node
{
    ll cnt;//某一位是7
    ll sum;//每一位加起来的和是7的整数倍
    ll sqsum;//本身是七的整数倍
} dp[20][10][10];

int digit[25];
ll p[25];

void init()
{
    p[0]=1;
    for(int i=1; i<20; i++)
        p[i]=(p[i-1]*10)%mod;
    //如何给结构体中某一属性赋值??
//    for(int i=0; i<20; i++)
//    {
//        for(int j=0; j<10; j++)
//        {
//            for(int k=0; k<10; k++)
//            {
//                dp[i][j][k].cnt=-1;
//            }
//        }
//    }
}

node dfs(int len,int p1,int p2,bool limit)
{
    if(len==-1)
    {
        node pp;
        pp.cnt=(p1!=0&&p2!=0);
        pp.sum=pp.sqsum=0;
        return pp;
        // return 1;
    }
    if(limit==0&&dp[len][p1][p2].cnt)
        //if(limit==0&&dp[len][p1][p2].cnt!=-1)//并且当前的数位已经统计过
        return dp[len][p1][p2];
    ll up;
    if(limit==1)
        up=digit[len];
    else
        up=9;
    node pp,qq;//为什么不能集体定义????WA??
    qq.cnt=qq.sqsum=qq.sum=0;
    for (int i=0; i<=up; i++)
    {
        if(i==7)
            continue;
        pp=dfs(len-1,(p1+i)%7,(p2*10+i)%7,limit&&i==up);
        qq.cnt+=pp.cnt;
        qq.cnt%=mod;

        qq.sum+=(pp.sum+((p[len]*i)%mod)*pp.cnt%mod)%mod;
        qq.sum%=mod;

        qq.sqsum+=(pp.sqsum+((2*p[len]*i)%mod)*pp.sum)%mod;
        qq.sqsum%=mod;
        qq.sqsum+=(pp.cnt*p[len])%mod*p[len]%mod*i*i%mod;
        qq.sqsum%=mod;
    }
    if (limit==0)//是一个完整的状态,等到下一次dfs的时候可以直接返回
        dp[len][p1][p2]=qq;
    return qq;
}

ll solve(ll x)
{
    int num=0;//有多少个数位
    while(x)
    {
        digit[num++]=x%10;
//不知道为什么这一题++num就不对了
        x/=10;
    }
    return dfs(num-1,0,0,1).sqsum;//从高位,从上面往下面遍历
}

int main()
{
//    memset(dp,0,sizeof(dp));//数位dp貌似清空-1需要清一次、清空二为0则不需要写清空语句
    init();
    int t;
    cin>>t;
    while(t--)
    {
        ll l,r;
        cin>>l>>r;//定义成int会WA
        ll ans=solve(r)-solve(l-1);
        ans=(ans%mod+mod)%mod;//防止为负
        cout<<ans<<endl;
        //cout<<n+1-solve(n)<<endl;
        // 给了上下界cout<<solve(m)-solve(n-1)<<endl;
    }
    return 0;
}

待解决:

一些需要解决的问题都记录在上下文了,我已经不想看这一道题了

thinking:

这道题我改了几个小时???

本来还要下午写完看英语,然后,,,,写到现在还没写完,

真的是补了一天题,,,太菜了实在是,,恨铁不成刚啊,

为什么里面的node非要重新定义,不影响啊???

里面的cnt清不清或者清-1都没有影响

我要原地爆炸了

英语还没看,boom~

原文地址:https://www.cnblogs.com/OFSHK/p/12319647.html