【GDOI2018模拟8.12】求和
来源:互联网 发布:知乎日报打不开 编辑:程序博客网 时间:2024/06/08 07:36
Description
求
其中当
答案对2^30取模
n<=10^10,k<=40
Solution
首先是个懂数论的人都能把式子化成这样:
后面这东西直接用杜教筛做
关键我们要怎么求前面这东西呢?
考虑当n较小的时候,我们可以预处理出
你只需要线筛出每个数的最大指数mx
如果mx>k那么g(i)显然是0
否则我们引入
那么g(i)=
但是当n较大的时候呢?
我们设
我们可以发现
这个根据容斥原理退一下就好了
然后我们设
那么根据
如果我们求出了W,那么这个东西我们就可以直接暴力求了。
现在问题是W怎么求?
我们可以发现
因为狄利克雷卷积左边是
然后自己推一推就可以发现了
这样一来W我们就可以通过杜教筛来解决,总复杂度O(n^2/3)
如果常数写打了被卡,发现模数是2的幂可以直接位运算加速
其实也可以unsigned long long自然溢出_ (:з」∠) _
Code
#include <cmath>#include <cstdio>#include <cstring>#include <algorithm>#define fo(i,a,b) for(int i=a;i<=b;i++)using namespace std;typedef long long ll;const int N=1e7,mo=1<<30;ll h[N+5],h1[N+5],n,ans;int k,phi[N+5],p[N+5],f[N+5],lemuda[N+5],sum[N+5],mx[N+5],cnt[N+5],mu[N+5];bool bz[N+5],vis[N+5],vis1[N+5];ll mi(ll x,int y) { ll z=1; for(;y;y/=2,x=x*x) if (y&1) z=z*x; return z;}void prepare() { phi[1]=1;lemuda[1]=1;mu[1]=1; fo(i,2,N) { if (!bz[i]) p[++p[0]]=i,lemuda[i]=mu[i]=-1,phi[i]=i-1,mx[i]=cnt[i]=1,f[i]=i; fo(j,1,p[0]) { int k=i*p[j]; if (k>N) break; bz[k]=1;lemuda[k]=-lemuda[i]; if (p[j]==f[i]) cnt[k]=cnt[i]+1; else cnt[k]=1; mx[k]=max(mx[i],cnt[k]); if (!(i%p[j])) { phi[k]=phi[i]*p[j]; f[k]=p[j]; break; } phi[k]=phi[i]*phi[p[j]]; if (!f[k]) f[k]=p[j]; mu[k]=-mu[i]; } } fo(i,1,N) { sum[i]=lemuda[i]+mo; (sum[i]+=sum[i-1])&=(mo-1); phi[i]+=phi[i-1]; phi[i]=phi[i]&(mo-1); } f[1]=k; fo(i,2,N) { if (mx[i]<=k) f[i]=lemuda[i]*(k-mx[i]+1); else f[i]=0; (f[i]+=f[i-1]+mo)&=(mo-1); }}ll get_phi(ll x) { if (x<=N) return phi[x];int t=n/x; if (vis[t]) return h[t];ll ans; if (x&1) ans=(x%mo)*((x+1)/2%mo); else ans=(x/2%mo)*((x+1)%mo); ans=ans&(mo-1); for(ll l=2,r;l<=x;l=r+1) { r=x/(x/l); ans+=mo-(r-l+1)%mo*get_phi(x/l)%mo; ans=ans&(mo-1); } vis[t]=1;h[t]=ans; return ans;}ll get_lemuda(ll x) { if (x<=N) return sum[x];int t=n/x; if (vis1[t]) return h1[t]; ll ans=pow(x,1.0/2); for(ll l=2,r;l<=x;l=r+1) { r=x/(x/l); ans+=mo-(r-l+1)%mo*get_lemuda(x/l)%mo; ans=ans&(mo-1); } vis1[t]=1;h1[t]=ans; return ans;}ll solve(int d,ll n,ll y) { ll m=pow(n,1.0/(d+1)); ll ans=0; fo(i,1,m) { int z=mu[i]; if (!z) continue; if (lemuda[i]==-1&&!(d&1)) z=-z; ll x=mi(i,d+1); if (z==1) { if (n/x<=N) (ans+=sum[n/x])&=(mo-1); else (ans+=h1[x*y])&=(mo-1); } else { if (n/x<=N) (ans+=mo-sum[n/x])&=(mo-1); else (ans+=mo-h1[x*y])&=(mo-1); } } return ans;}int main() { scanf("%lld%d",&n,&k); prepare();get_phi(n);get_lemuda(n);ll la=0; for(ll l=1,r;l<=n;l=r+1) { r=n/(n/l);ll sum=0,now=0; if (n/l<=N) sum=2*phi[n/l]-1; else sum=2*h[l]-1; sum&=(mo-1); if (r<=N) now=f[r]; else fo(j,1,k) (now+=solve(j,r,n/l))&=(mo-1); ll tmp=now-la; if (tmp<0) tmp+=mo; tmp=tmp&(mo-1); tmp=tmp*sum&(mo-1); (ans+=tmp)&=(mo-1); la=now; } printf("%lld\n",ans);}
阅读全文
0 0
- 【GDOI2018模拟8.12】求和
- 【GDOI2018模拟8.12】求和
- [JZOJ5261]【GDOI2018模拟8.12】求和
- 【JZOJ5262】【GDOI2018模拟8.12】树
- 【GDOI2018模拟8.12】区间第k小
- 【GDOI2018模拟8.12】区间第k小
- 【GDOI2018模拟7.6】吃干饭
- 【GDOI2018模拟7.9】期末考试
- 【GDOI2018模拟7.8】质数
- 【GDOI2018模拟7.8】矩阵
- 【GDOI2018模拟7.10】B
- 【GDOI2018模拟7.10】C
- 【GDOI2018模拟7.10】B
- 【GDOI2018模拟7.10】C
- 【GDOI2018模拟7.12】B
- 【GDOI2018模拟7.12】C
- 【GDOI2018模拟7.12】A
- 【GDOI2018模拟7.10】C
- 解决散列表冲突问题-开放定址法
- IOS应用内购买(In App Purchase)总结
- hdu2544 最短路,dijstra(模板)
- 使用腾讯云 GPU 学习深度学习系列之四:深度学习的特征工程
- Android避免内存溢出(Out of Memory)方法总结
- 【GDOI2018模拟8.12】求和
- 字符设备和块设备的区别
- Thin Plate Spline (薄板样条函数)
- 与scroll相关的兼容性问题
- JAVA最长子序列
- java-3-多线程-初步了解-3-同步
- List自定义排序 (例子省份排序)
- Eclipse恢复已删除的文件和代码、svn使用了还原,但本地的没有提交找回没提交代码的方法
- 《hbase学习》-04-HBase数据快速导入之ImportTsv