题解:P8245 [COCI2013-2014#3] PAROVI
题意
定义两个整数
之间的距离为这两个整数所有对应位上的数的差的绝对值之和,记为 。特别地,如果 两数的位数不相同,则在位数较小的数前补足前导 。 现在,给定两个整数
,请你求出所有在区间 内的整数对的距离和。请对 取模。
分析
考虑记录在每一个数位上每个数出现了多少次。
令
这样我们就可以枚举数码
我们只需要解决
首先将问题转化为求
上面所求的可以使用数位 dp 解决。
时间复杂度
Code
#include<bits/stdc++.h> using namespace std; #define mod 1000000007 int64_t ksm(int64_t x, int l) { int64_t ret=1; for(;l;l>>=1, x=x*x%mod) if(l&1) ret=ret*x%mod; return ret; } int64_t cnt[50004][10]; int64_t tag[50004]; int64_t calc(const string &s, int p, int op) { if(p<0) return 1; int64_t mx=s[p]^48; int64_t w=ksm(10, p); if(p) tag[p-1]=((tag[p-1]+op*ksm(10, p-1)*mx)%mod+mod)%mod; for(int i=0;i<mx;i++) cnt[p][i]=((cnt[p][i]+w*op)%mod+mod)%mod; int64_t ret=mx*w%mod; int64_t tmp=calc(s, p-1, op); cnt[p][mx]=((cnt[p][mx]+tmp*op)%mod+mod)%mod; return (ret+tmp)%mod; } string a, b; void reduce(string &s) { reverse(s.begin(), s.end()); for(auto &c:s) { if(c^48) {c--; break;} c='9'; } if(s.back()=='0') s.pop_back(); reverse(s.begin(), s.end()); } int main() { cin>>a>>b; reduce(a); reverse(b.begin(), b.end()); reverse(a.begin(), a.end()); while(a.size()<b.size()) a.push_back('0'); calc(b, b.size()-1, 1); calc(a, a.size()-1, -1); for(int i=b.size()-1;~i;i--) { tag[i]=(tag[i]+tag[i+1])%mod; for(int j=0;j<10;j++) cnt[i][j]=(cnt[i][j]+tag[i])%mod; } int64_t ans=0; for(int i=b.size()-1;~i;i--) for(int j=0;j<10;j++) for(int k=j+1;k<10;k++) ans=(ans+(k-j)*cnt[i][j]%mod*cnt[i][k])%mod; cout<<ans*2%mod; }
本文作者:Jimmy-LEEE
本文链接:https://www.cnblogs.com/redacted-area/p/18514171
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步