luogu P4884 多少个1?
LINK:多少个1?
题目要求:\sum_{i=0}^{n-1}10^i \equiv k \mod m 最小的n。
看起来很难求的样子 这个同余式 看起来只能暴力枚举。
不过既然是同余 我们等式两边就可以同时进行加减乘 运算。
考虑转换成我们熟悉的模型 而这个形式比较像高次同余方程。
等式两边同乘 9 再加一 等式变成 10^n\equiv 9*k+1\mod m
显然这是一个高次同余方程我们直接BSGS即可。
但是m和10显然有可能是不互质的 所以我们需要一个扩展BSGS (扩展拔山盖世算法。
哦 m保证为质数 那打扰了。。
但是 模数有可能m>int 所以我们需要龟速乘 这样的话复杂度就是log^2的了 且log是跑满的。所以非常的慢。
const ll MAXN=100010;
ll mod,n;
map<ll,ll>H;
inline ll gsc(ll a,ll b)
{
ll cnt=0;
while(b)
{
if(b&1)cnt=(cnt+a)%mod;
b=b>>1;a=(a+a)%mod;
}
return cnt;
}
inline ll BSGS()//求 10^x%mod=n; x>1
{
ll w=(ll)sqrt(mod*1.0)+1;
ll ww=1;
rep(1,w,i)
{
ww=ww*10%mod;
ll cc=gsc(ww,n)%mod;
H[cc]=max(H[cc],i);
}
ll cc=ww;
rep(1,w,i)
{
if(H.find(cc)!=H.end())return i*w-H[cc];
if(cc==n)return i*w;
cc=gsc(cc,ww)%mod;
}
return 114514;
}
int main()
{
freopen("1.in","r",stdin);
get(n);get(mod);
n=n*9+1%mod;
putl(BSGS());
return 0;
}
其实完全不需要快速幂 我们颠倒一下 两部分先求出右部分即可。
当然 也可以快速幂了 那个时候不过不能再龟速乘了。
考虑一种较快的乘法:
比较常见的 是转long double 的快速乘。
long double精度不够的时候 会丢弃后面的位。
考虑 a%p=a-(a/p)p; 那么 ab%p=ab-(ab/p)*p;
如果p过大的时候 我们会丢掉 a*b后面的一些位 但是这些位同时也产生不了贡献
所以 这样做是可行的。具体的 我再思考一下。
inline LL ksc(LL a,LL b,LL p)//long double版本的快速乘
{
a%=p;b%=p;
long long c=(long double)a*b/p;
long long ans=a*b-c*p;
if(ans<0) ans+=p;
else if(ans>=p) ans-=p;
return ans;
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 现代计算机视觉入门之:什么是图片特征编码
· .NET 9 new features-C#13新的锁类型和语义
· Linux系统下SQL Server数据库镜像配置全流程详解
· Sdcb Chats 技术博客:数据库 ID 选型的曲折之路 - 从 Guid 到自增 ID,再到
· Winform-耗时操作导致界面渲染滞后
· Phi小模型开发教程:C#使用本地模型Phi视觉模型分析图像,实现图片分类、搜索等功能
· 语音处理 开源项目 EchoSharp
· drools 规则引擎和 solon-flow 哪个好?solon-flow 简明教程