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

题目链接:点击传送

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

Time Limit: 1000/500 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)


Problem 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的整数倍;

  现在问题来了:吉哥想知道在一定区间内和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
 
Source
思路:
dp[mod][sum][k]表示在pos的位置前面数字对7取模,前面数字之和对7取模,前面是否出现过7;
为什么不能直接返回s*s呢,因为你的标记是mod,sum,k;两个数前面的那部分可能会使得mod,sum,k相等,比如,07,跟70;
然后一个数的平方利用开方来处理;
详见代码。
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<iostream>
#include<cstdio>
#include<cmath>
#include<string>
#include<queue>
#include<algorithm>
#include<stack>
#include<cstring>
#include<vector>
#include<list>
#include<set>
#include<map>
using namespace std;
#define ll long long
#define pi (4*atan(1.0))
#define eps 1e-4
#define bug(x)  cout<<"bug"<<x<<endl;
const int N=2e3+10,M=9e3+10,inf=2147483647;
const ll INF=1e18+10,mod=1e9+7;
struct nsq
{
    ll num,sum,sqsum;
    nsq(){}
    nsq(ll a,ll b,ll c)
    {
        num=a,sum=b,sqsum=c;
    }
};
nsq f[20][10][10][3];
ll bit[20];
ll qpow(ll a,ll b)
{
    ll ans=1;
    while(b)
    {
        if(b&1)ans=(ans*a)%mod;
        b>>=1;
        a=(a*a)%mod;
    }
    return ans;
}
ll qmul(ll a,ll b)
{
    ll ans=0;
    while(b)
    {
        if(b&1)ans=(ans+a)%mod;
        b>>=1;
        a=(a+a)%mod;
    }
    return ans;
}
ll add(ll a,ll b)
{
    return (a+b)%mod;
}
ll del(ll a,ll b)
{
    return ((a-b)%mod+mod)%mod;
}
nsq dp(int pos,int sum,int mod,int k,int flag)
{
    if(pos==0)return nsq(sum&&mod&&!k,0,0);
    if(flag&&f[pos][sum][mod][k].num!=-1)return f[pos][sum][mod][k];
    int x=flag?9:bit[pos];
    nsq ans(0,0,0);
    for(int i=0;i<=x;i++)
    {
        nsq nnnn=dp(pos-1,(sum+i)%7,(mod*10+i)%7,k||i==7,flag||i<x);
        ans.num=add(ans.num,nnnn.num);
        ans.sum=add(ans.sum,add(nnnn.sum,qmul(nnnn.num,qmul(1LL*i,qpow(10,pos-1)))));
        ans.sqsum=add(ans.sqsum,add(nnnn.sqsum,qmul(nnnn.num,qmul(1LL*i*i,qpow(10,2*pos-2)))));
        ans.sqsum=add(ans.sqsum,qmul(nnnn.sum,qmul(2LL*i,qpow(10,pos-1))));
    }
    if(flag)f[pos][sum][mod][k]=ans;
    return ans;
}
nsq getans(ll x)
{
    int len=0;
    while(x)
    {
        bit[++len]=x%10;
        x/=10;
    }
    return dp(len,0,0,0,0);
}
int main()
{
    int T,cas=1;
    memset(f,-1,sizeof(f));
    scanf("%d",&T);
    while(T--)
    {
        ll l,r;
        scanf("%lld%lld",&l,&r);
        printf("%lld
",del(getans(r).sqsum,getans(l-1).sqsum));
    }
    return 0;
}

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

Time Limit: 1000/500 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 3846    Accepted Submission(s): 1230


Problem 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的整数倍;

  现在问题来了:吉哥想知道在一定区间内和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
 
Source
原文地址:https://www.cnblogs.com/jhz033/p/6613355.html