码迷,mamicode.com
首页 > 其他好文 > 详细

恨 7 不成妻

时间:2019-11-12 20:29:30      阅读:110      评论:0      收藏:0      [点我收藏+]

标签:utc   pos   答案   putchar   uri   namespace   mem   暴力   计数   

https://loj.ac/problem/10168

题目描述

??求出一段区间内与\(7\)无关的数的平方和,我们定义这个数与\(7\)有关当且仅当这个数满足下列条件之一:1、某一位为\(7\);2、数位和为\(7\)的倍数;3、这个数本身是\(7\)的倍数。

思路

??这题并不算裸的数位\(dp\)题,显然如果对于计数我们很容易得到这个区间内满足条件的个数,而为了使数位\(dp\)\(dp\)能够有子状态重叠,我们仍然考虑计数,不过对于每一位的处理可以转化为记录它的状态,我们用一个三元组\((cnt,sum,sqsum)\)描述这个状态,它代表这这个状态下符合条件的数的个数\(cnt\),这后几位数的和对答案的贡献,后几位的平方和对答案的贡献。显然\(cnt\)可以直接求出来。

??而对于另两个值,我们考虑当前位为\(pos\),选取的值为\(i\)\(tmp\)为传回来的答案,那么显然\(ans.sum=(ans.sum+tmp.cnt*10^{pos}*i)\),因为每一个符合条件的数这一位都为\(i\),对和有\(i*10^{pos}\)的贡献。而对于平方和,我们要求的实际就是\(\sum(i*10^{pos}+x)^2\)(\(x\)符合条件),所以我们暴力把它拆开,得到\(\sum (i^2*10^{2*pos}+2*i*10^{pos}*x+x^2)\),再把求和拆开得\(\sum i^2*10^{2*pos}+\sum 2*i*10^{pos}*x+\sum x^2\),这个我们可以用得到的三元组\((cnt,sum,sqsum)\)直接转移。

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;

struct Node
{
    ll cnt,sum,sqsum;
    Node(ll cnt=0,ll sum=0,ll sqsum=0):cnt(cnt),sum(sum),sqsum(sqsum){}
};
Node dp[31][11][11];
ll p[30];
ll power[30];

ll sqr(ll x)
{
    return x*x%mod;
}
Node dfs(ll pos,ll s1,ll s2,ll flag)
{
//  cout<<pos<<'z'<<endl;
    if(pos==0)
        return Node(s1!=0&&s2!=0,0,0);
    if(!flag&&~dp[pos][s1][s2].cnt)return dp[pos][s1][s2];
    Node tmp,ans=Node(0,0,0);
    ll end=flag?p[pos]:9;
//  cout<<pos<<' '<<end<<endl;
    for(ll i=0;i<=end;i++)
    {
        if(i==7)continue ;
        tmp=dfs(pos-1,(s1+i)%7,(s2*10+i)%7,flag&&i==end);
        ans.cnt+=tmp.cnt;
        ans.cnt%=mod;
        ans.sum+=(tmp.sum+tmp.cnt*power[pos]%mod*i%mod)%mod;
        ans.sum%=mod;
        ans.sqsum+=(tmp.sqsum+2*power[pos]*i%mod*tmp.sum%mod+sqr(i)*sqr(power[pos])%mod*tmp.cnt%mod)%mod;
        ans.sqsum%=mod;
    }
    if(!flag)dp[pos][s1][s2]=ans;
    return ans;
}
ll solve(ll x)
{
    memset(p,0,sizeof(p));
    ll cnt=0;
    while(x)
    {
        p[++cnt]=x%10;
        x/=10;
    }
    return dfs(cnt,0,0,1).sqsum;
}

ll read()
{
    ll res=0,w=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){res=(res<<3)+(res<<1)+(ch^48);ch=getchar();}
    return res*w;
}
void write(ll x)
{
    if(x<0){putchar('-');x=-x;}
    if(x>9)write(x/10);
    putchar(x%10+'0');
}
void writeln(ll x)
{
    write(x);
    putchar('\n');
}

int main()
{
    ll t=read();
    power[1]=1;
    for(ll i=2;i<=21;i++)
        power[i]=(power[i-1]*10)%mod;
    for(ll i=0;i<=21;i++)
        for(ll j=0;j<=10;j++)
            for(ll k=0;k<=10;k++)
                dp[i][j][k].cnt=-1;
    while(t--)
    {
        ll l=read(),r=read();
        writeln(((solve(r)-solve(l-1))%mod+mod)%mod);
    }
}

恨 7 不成妻

标签:utc   pos   答案   putchar   uri   namespace   mem   暴力   计数   

原文地址:https://www.cnblogs.com/fangbozhen/p/11844402.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!