好久没碰数论的东西了,已经完全生疏了。
做了几道数论题总结一下。
大意:
求 
思路:
隐约记得哪次比赛做过原题,也做出来了,但是现在还是有点懵了。。。
先把式子转化一下吧

那么整个式子就稍微有点样子了。
接下来对每一个l求对应的r
令
,
r=max(i),i*t<=n;
得到:
r=k/t;
这是对于每一个l对应的r,对于
里面的
,i在连续的区间里是一个等差数列,那么直接套公式即可。
- #include<bits/stdc++.h>
- using namespace std;
- #define ll long long
- #define mx *max_element
- const ll N=2e5+10;
- ll n,k,r;
- int main()
- {ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
- cin>>n>>k;
- ll ans=n*k;
- for(int l=1;l<=n;l=r+1)
- {
- ll t=k/l;
- if(t!=0) r=min(k/t,n);
- else r=n;
- ans-=t*(r-l+1)*(l+r)/2;
- }
- cout<<ans<<endl;
- return 0;
- }
虽然是一道省选-,但代码是真的短。
大意:
思路:
首先,这个
就是求
,也就是我们所熟知的求数字约数的函数,换句话说,这里
,其中
.
不妨做一个转换,改为先枚举d,则
,
到这一步,要求f(x)那就是轻而易举了。
最后,由于i是从l到r,那么
,这样的话写一个函数就好了。
- #include<bits/stdc++.h>
- using namespace std;
- #define ll long long
- const ll mod=998244353;
- ll a,b;
- ll f(ll x)
- {
- ll ans=0;
- ll l,r;
- for(ll l=1;l<=x;l=r+1)
- {
- r=x/(x/l);
- ans=(ans+(x/l)*(r-l+1)%mod)%mod;
- }
- return ans%mod;
- }
- int main()
- {
- cin>>a>>b;
- cout<<(f(b)-f(a-1)+mod)%mod<<endl;
- return 0;
- }
点是有点多,但都想到了就挺板的。
大意:
思路:
这里有一个限制是i!=j,所以不妨把式子转化一下。

其中
这个就是我们在第一个问题里讨论的东西,那应该就很好处理了。
然后是后面的东西,如果展开的话:


这里的第一项就不用说了,第二三项其实跟上面讨论的
是一个道理,只是加了一个常数而已。
那么最后一项,
,与上一个的区别只是i的次数提高了一项,但如果照搬之前的思路,求等差数列的和的话,
,那么这一项也解决了,那么整个题目到这里也就ok了。
还想说一个坑点,就是题目里这个取模的数居然不是质数。。。
也怪我傻,998244353,1e9+7见多了,看啥都像质数
所以这里的逆元得自己提前去求好了,不能用快速幂。
- #include<bits/stdc++.h>
- using namespace std;
- #define ll long long
- const ll mod=19940417;
- const ll inv2=9970209;
- const ll inv6=3323403;
- #define endl '\n'
- ll n,m;
- ll sd(ll x)
- {
- return x*(x+1)%mod*(2*x+1)%mod*inv6%mod;
- }
- ll sdd(ll x)
- {
- return x*(x+1)%mod*inv2%mod;
- }
- ll f(ll n)//求sum(n-(n/i)*i)
- {
- ll sum=n*n%mod;
- //cout<<sum<<endl;
- for(ll l=1,r;l<=n;l=r+1)
- {
- ll t=n/l;
- r=n/t;
- sum=(sum-t*(sdd(r)-sdd(l-1)+mod)%mod+mod)%mod;
- //cout<<sum<<endl;
- }
- return sum;
- }
- int main()
- {
- cin>>n>>m;
- //cout<<sdd(4)<<' '<<sdd(3)<<endl;
- //cout<<f(n)<<" "<<f(m)<<endl;
- ll sum=0,ans=0;
- sum=(sum+f(n))%mod;
- sum=(sum*f(m))%mod;
- ans=sum;sum=0;
- for(ll l=1,r;l<=min(n,m);l=r+1)
- {
- r=min(n/(n/l),m/(m/l));
- sum+=(r-l+1+mod)%mod*n%mod*m%mod;
- sum-=(r-l+1+mod)%mod*(l+r)%mod*((n/l)*m%mod+(m/l)*n%mod)%mod*inv2%mod;
- sum+=(sd(r)-sd(l-1)+mod)%mod*(n/l)%mod*(m/l)%mod;
- sum=(sum+mod)%mod;
- }
- cout<<(ans-sum+mod)%mod<<endl;
- return 0;
- }
大致就先这样,后面可能会补新的题