题意大意
给定游程编码表示的整数 N 和整数 M,游标编码即由 K 组 (ci,li) 描述,表示数字 ci 重复 li 次,求 ⌊MN⌋mod10007。
由于 li 可达 109,所以无法直接构造 N。
解题思路
维护 Nmod(M×10007)。设 Mod=M×10007,则答案为 MNmodModmod10007 。
为什么模数是 M×10007?
题目要求的是商 Q=⌊N/M⌋ 对 10007 取模的结果。
- 若只对 M 取模,只能得到余数,商的信息完全丢失。
- 若只对 10007 取模,由于中间过程涉及整除,模运算性质不直接适用。
为了方便,我们设 P=10007,我们维护 R=Nmod(M×P)。
根据带余除法,存在整数 k 使得 N=k⋅(M⋅P)+R。
两边同时除以 M 并向下取整:
⌊MN⌋=k⋅P+⌊MR⌋
对上式取模 P:
⌊MN⌋modP=(k⋅P+⌊MR⌋)modP=⌊MR⌋modP
因为 0≤R<M×P,所以 0≤⌊MR⌋<P。
这意味着 ⌊MR⌋ 本身就是小于 P 的非负整数,直接等于它模 P 的结果。
结论:只要算出 Nmod(M×10007),将其除以 M 取整,即为答案。直接计算需除以 9,但 M 可能含因数 3,导致模逆元不存在。解决方法:
- 计算 r=10ymod(9×Mod)。
- 由于 10y≡1(mod9),r−1 必能被 9 整除,故 9r−1 为整数。
每段数字 x 重复 y 次的数值可表示为:
x×910y−1
状态更新公式
维护当前余数 ans:
ans=(ans×r+x×9r−1)modMod
其中 r=10ymod(9×Mod)。
Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| #include<bits/stdc++.h> using namespace std; typedef long long ll; ll T,m,ans,Mod; ll qpow(ll a,ll b,ll mod){ ll res=1; while(b){ if(b&1)res=res*a%mod; a=a*a%mod; b>>=1; } return res; } int main(){ cin>>T>>m; Mod=m*10007; while(T--){ ll x,y; cin>>x>>y; ll r=qpow(10,y,Mod*9); ans=(ans*r%Mod+x*(r-1)/9)%Mod; } cout<<(ans/m)%10007; return 0; }
|