题解:P10704 救赎(Redemption)

数论题,先看数据范围,发现 nm 都非常大,但是 i=1i=nai109

解以上不等式得不同的 ai 大约有 40000 个。记有 cnt 个不同的 ai,所以显然有一种 O(k2) 的做法。

期望得分:70 分。

考虑优化,设去重后数组为 w,观察数据可得不同的 ai×aj 有可能再向下取整后变成一样的值。

先将 w 排序,对于每个 wi,首先确定
mwiwj 相同时 j 的取值范围。观察发现,mwiwj 相同时 j 是连续的。所以考虑二分求得左右边界,通过前缀和维护这段区间内的数的总个数,可求得该段的贡献。

题目背景好评

Code:

复制代码
复制代码
signed main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
    }
    sort(a+1,a+n+1);
    for(int i=1;i<=n;i++)
    {
        if(a[i]!=a[i-1])
        {
            b[++cnt1]=a[i];
            cnt[cnt1]=1;
        }
        else
        {
            cnt[cnt1]++;
        }
    }
    for(int i=1;i<=cnt1;i++)
    {
        sum1[i]=sum1[i-1]+cnt[i];
    }
    int now=0;
    int l3=0,r3=0;
    for(int i=1;i<=cnt1;i++)
    {
        sum=(sum+1ll*(m/(b[i]*b[i]))*cnt[i]%mod*cnt[i])%mod;
        if(i==cnt1)
        {
            continue;
        }
        l3=i+1;
        now=(m/(b[i]*b[l3]));
        while(l3<=cnt1)
        {
            r3=check(i,now,l3);
            ret=(ret+now*cnt[i]%mod*(sum1[r3]-sum1[l3-1]))%mod;
            l3=r3+1;
            if(l3>cnt1)
            {
                break;
            }
            now=m/(b[i]*b[l3]); 
        }
    }
    cout<<(ret*2+sum)%mod;
    return 0;
}
复制代码
复制代码

 

posted @   _Acheron  阅读(3)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek “源神”启动!「GitHub 热点速览」
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· 2 本地部署DeepSeek模型构建本地知识库+联网搜索详细步骤
点击右上角即可分享
微信分享提示
人是可以改变一切的,世上的一切。