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

来源:互联网 发布:java字符串替换某一位 编辑:程序博客网 时间:2024/05/17 13:09

[L,R]中不满足以下任意一条的数的平方和

1 整数中某一位是7

2 整数的每一位加起来的和是7的整数倍

3 这个整数是7的整数倍;


一眼看去又是一个数位dp,但是怎么统计平方和呢?

假设我们在统计最高位为x的n个数的平方和

i=1n(x+a)2=n×x2+2x×i=1nai+i=1na2i

其中和x相关的贡献是前两项。也就是说,我们统计能接在当前前缀后面的后缀的个数和后缀的和,就可以计算出x对整个平方和的贡献。

怎么统计后缀和呢?

i=1n(x+ai)=n×x+i=1nai

也需要统计后缀的个数。

那么照着这个统计下去就好了。


因为一开始写的时候没有想太多就强行写了三遍dfs。。。

有空重写一遍

#include<bits/stdc++.h>using namespace std;#define LL long long const int maxn = 20,mod = 1e9 + 7;int num[maxn];LL ten[maxn * 2];LL cnted[maxn][2][7][7];LL count(int pos,bool bnd,int left,int sumer){    if(pos < 0) return left != 0 && sumer != 0;    LL & ncnt = cnted[pos][bnd][left][sumer];    if(~ncnt) return ncnt;    ncnt = 0;    int bound = bnd ? num[pos] : 9;    for(int i=0;i<=bound;i++){        if(i == 7) continue;        (ncnt += count(pos-1                     ,bnd && bound == i                     ,(left * 10 + i ) % 7                     ,(sumer + i ) % 7 ) ) %= mod;    }    return ncnt;}LL sumed[maxn][2][7][7];LL sum(int pos,bool bnd,int left,int sumer){    if(pos < 0) return 0;    LL & nsum = sumed[pos][bnd][left][sumer];    if(~nsum) return nsum;    nsum = 0;    int bound = bnd ? num[pos] : 9;    for(int i=0;i<=bound;i++){        if(i == 7) continue;        (nsum += sum (pos-1                     ,bnd && bound == i                     ,(left * 10 + i ) % 7                     ,(sumer + i ) % 7 ) ) %= mod;        (nsum += (count(pos-1                       ,bnd && bound == i                       ,(left * 10 + i ) % 7                       ,(sumer + i ) % 7 )                * i                 * ten[pos]) % mod ) %= mod;    }    return nsum;}LL dp[maxn][2][7][7];LL dfs(int pos,bool bnd,int left,int sumer){    if(pos < 0) return 0;    LL & ndp = dp[pos][bnd][left][sumer];    if(~ndp) return ndp;    ndp = 0;    int bound = bnd ? num[pos] : 9;    for(int i=0;i<=bound;i++){        if(i == 7) continue;        (ndp += dfs(pos-1                   ,bnd && bound == i                   ,(left * 10 + i ) % 7                   ,(sumer+ i ) % 7 ) ) %= mod;        (ndp += ((count(pos-1                      ,bnd && bound == i                      ,(left * 10 + i ) % 7                      ,(sumer+ i ) % 7 )                * i * i ) % mod                * ten[pos * 2]) % mod ) %= mod;        (ndp += ((sum(pos-1                    ,bnd && bound == i                    ,(left * 10 + i ) % 7                    ,(sumer+ i ) % 7 )                * i * 2 ) % mod                * ten[pos]) % mod ) %= mod;    }    return ndp;}LL cal(LL x){    int len = 0;    while(x){        num[len++] = x % 10;        x /= 10;    }    memset(cnted,-1,sizeof(cnted));    memset(sumed,-1,sizeof(sumed));    memset(dp,-1,sizeof(dp));    return dfs(len-1,true,0,0);}int main(){    ten[0] = 1;    for(int i=1;i<maxn * 2;i++) ten[i] = (ten[i-1] * 10 ) % mod;    int T;    scanf("%d",&T);    LL l,r;    while(T-- && ~scanf("%I64d %I64d",&l,&r)){        printf("%I64d\n",(cal(r) - cal(l-1) + mod) % mod);    }    return 0;}

重写之后果然短了不少

#include<bits/stdc++.h>using namespace std;#define LL long long const int maxn = 20,mod = 1e9 + 7;LL dp[maxn][2][7][7];LL sum[maxn][2][7][7];LL cnt[maxn][2][7][7];bool vis[maxn][2][7][7];int num[maxn];LL ten[maxn * 2];LL cnter(int pos,bool bnd,int lef,int mor,int nex){    lef = (lef * 10 + nex) % 7;    mor = (mor + nex) % 7;    if(pos == 0)         return mor != 0 && lef != 0;    return cnt[pos-1][bnd && nex == num[pos]][lef][mor];}LL sumer(int pos,bool bnd,int lef,int mor,int nex){    if(pos == 0) return 0;    lef = (lef * 10 + nex) % 7;    mor = (mor + nex) % 7;    return sum[pos-1][bnd && nex == num[pos]][lef][mor];}#define nexter pos,bnd,lef,mor,iLL dfs(int pos,bool bnd,int lef,int mor){    if(pos < 0) return 0;    if(vis[pos][bnd][lef][mor])        return dp[pos][bnd][lef][mor];    LL & ndp =  dp [pos][bnd][lef][mor];    LL & ncnt = cnt[pos][bnd][lef][mor];    LL & nsum = sum[pos][bnd][lef][mor];    ndp = ncnt = nsum = 0;    int bound = bnd ? num[pos] : 9;    for(int i=0;i<=bound;i++){        if(i == 7) continue;        (ndp += dfs(pos-1,bnd && i == bound,(lef*10+i)%7,(mor+i)%7)) %= mod;        (ncnt += cnter(nexter) ) %= mod;        (nsum += sumer(nexter) ) %= mod;        (nsum += ((cnter(nexter) * i ) % mod * ten[pos] ) % mod ) %= mod;         (ndp += ((cnter(nexter) * i * i ) % mod * ten[pos * 2]) % mod ) %= mod;        (ndp += ((sumer(nexter) * i * 2 ) % mod * ten[pos] ) % mod ) %= mod;    }    vis[pos][bnd][lef][mor] = true;    return ndp;}LL cal(LL n){    int len = 0;    while(n){        num[len++] = n % 10;        n /= 10;    }    memset(vis,0,sizeof(vis));    return dfs(len-1,true,0,0);}int main(){    ten[0] = 1;    for(int i=1;i<maxn * 2;i++)        ten[i] = (ten[i-1] * 10) % mod;    int T;    scanf("%d",&T);    LL l,r;    while(T-- && ~scanf("%I64d %I64d",&l,&r)){        printf("%I64d\n",(cal(r) - cal(l-1) + mod ) % mod);    }    return 0;}
0 0