恨7不成妻
恨 7 不成妻
题目描述
单身!
依然单身!
吉哥依然单身!
DS 级码农吉哥依然单身!
所以,他平生最恨情人节,不管是 214 还是 77,他都讨厌!
吉哥观察了 214 和 77 这两个数,发现:
最终,他发现原来这一切归根到底都是因为和 7 有关!所以,他现在甚至讨厌一切和 7 有关的数!
什么样的数和 7 有关呢?如果一个整数符合下面三个条件之一,那么我们就说这个整数和 7 有关:
- 整数中某一位是 7;
- 整数的每一位加起来的和是 7 的整数倍;
- 这个整数是 7 的整数倍。
现在问题来了:吉哥想知道在一定区间内和 7 无关的数字的平方和。
输入
输入数据的第一行是测试数据组数 T,然后接下来的 T 行表示 T 组测试数据。
每组数据在一行内包含两个正整数 L, R。
输出
对于每组数据,请计算 [L,R] 中和 7 无关的数字的平方和,并将结果对
样例输入
3
1 9
10 11
17 17
样例输出
236
221
0
数据范围与提示
对于全部数据
解题思路
可以用记忆化搜索。
int dfs(int len, int mod, int sum, bool fp)
len:当前搜索到了第几位。
mod:当前搜出的数模7的余数。
sum:当前搜索到的数的各位之和。
fp:当前这一位有没有达到上界(true:达到了,false:没达到)。
for (int i = 0; i <= fpmax; i++)
{
if (i == 7)
continue;
int re;
re = dfs(len - 1, (mod * 10 + i) % 7, (sum + i) % 7, fp && i == fpmax);
}
fpmax:当前这一位的最大值。(如:1234,第一位是1,第二位是2)。
i:这一位选的数。
因为题目上说要求平方和,所以我们还得推出公式:
举个例子,求
我们发现如果想求出答案,必须知道三个数:
和 平方和 数量
所以,我们需要一个结构体,维护这三个数:
struct node{
int sum;//1 和
int psum;//2 平方和
int cnt;//3 数量
void init(){
cnt=sum=psum=0;
}
};
显而易见答案就是第二个数(平方和)。
每次搜索就统计这三个变量:
- cnt:直接累加。
- sum:每次累加后还要加一个30。
- psum:根据推出的公式,
。
ret.cnt=(ret.cnt+re.cnt);
ret.sum=((ret.sum+re.sum)+((re.cnt*i)*po[len]));
ret.psum=(ret.psum+re.psum);
ret.psum=((ret.psum+(((po[len]*po[len])*i*i)*re.cnt)));
ret.psum=(ret.psum+((2*po[len]*i)*re.sum));
po:po[1]=10
,po[2]=100
,以此类推。
代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define Mod 1e9+7
struct node{
int cnt;
int sum;
int psum;
void init(){
cnt=sum=psum=0;
}
};
node dp[100][20][20];
int digit[100];
int po[100];
bool vis[100][20][20];
inline node dfs(int len, int mod, int sum, bool fp)
{
if (!len)
{
node ret;
ret.init();
if(mod&&sum%7){
ret.cnt=1;
}
return ret;
}
if (vis[len][mod][sum]&&!fp)
return dp[len][mod][sum];
node ret;
ret.init();
int fpmax = fp ? digit[len] : 9;
for (int i = 0; i <= fpmax; i++)
{
if (i == 7)
continue;
node re;
re = dfs(len - 1, (mod * 10 + i) % 7, (sum + i) % 7, fp && i == fpmax);
ret.cnt=(ret.cnt+re.cnt)%Mod;
ret.sum=((ret.sum+re.sum)%Mod+((re.cnt*i)%Mod*po[len]))%Mod;
ret.psum=(ret.psum+re.psum)%Mod;
ret.psum=((ret.psum+(((po[len]*po[len])%Mod*i*i)%Mod*re.cnt)%Mod)%Mod)%Mod;
ret.psum=(ret.psum+((2*po[len]*i)%Mod*re.sum)%Mod)%Mod;
}
if (!fp){
dp[len][mod][sum] = ret;
vis[len][mod][sum]=1;
}
return ret;
}
inline int f(int n)
{
int len = 0;
while (n)
{
digit[++len] = n % 10;
n /= 10;
}
return dfs(len, 0, 0, true).psum%Mod;
}
signed main()
{
int n;
scanf("%lld",&n);
po[1]=1;
for(int i=2;i<=20;i++){
po[i]=(po[i-1]*10)%Mod;
}
for(int i=1;i<=n;i++){
int l,r;
scanf("%lld%lld",&l,&r);
printf("%lld\n",(f(r)-f(l-1)+Mod)%Mod);
}
return 0;
}
本文来自博客园,作者:maniubi,转载请注明原文链接:https://www.cnblogs.com/maniubi/p/16418449.html,orz
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效