恨 7 不成妻
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∗10pos∗i),因为每一个符合条件的数这一位都为i,对和有i∗10pos的贡献。而对于平方和,我们要求的实际就是∑(i∗10pos+x)2(x符合条件),所以我们暴力把它拆开,得到∑(i2∗102∗pos+2∗i∗10pos∗x+x2),再把求和拆开得∑i2∗102∗pos+∑2∗i∗10pos∗x+∑x2,这个我们可以用得到的三元组(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);
}
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 现代计算机视觉入门之:什么是图片特征编码
· .NET 9 new features-C#13新的锁类型和语义
· Spring AI + Ollama 实现 deepseek-r1 的API服务和调用
· 《HelloGitHub》第 106 期
· 数据库服务器 SQL Server 版本升级公告
· 深入理解Mybatis分库分表执行原理
· 使用 Dify + LLM 构建精确任务处理应用