题面
思路
这道题显示是要求前缀和,观察一下1-8的排列,显然发现如果一个数ai=pk也就是仅有一个素因子,那么响应的因子肯定会在这里有一个断点也就是会加一
我们看当n=8时
n=2 时 有2:1 ans=2*1=2
n=3 时 有2:1+1 3:1 ans = 2*2+3
n=4 时 有2:1+1+2 3:1 4:1 ans = 4*2+3+4
⋯
n=8 时 有2:1+1+2+2+2+2+3;⋯
先考虑n=8时对所有的贡献,
显然2从2~8都有1的贡献,也即是2(8-2+1),枚举3~8得到
2(8-2+1)+3(8-3+1)+⋯+8(8-8+1).
这个式子我们单独拆开来看
x∗(n−x+1)=x∗(n+1)−x2;对这个式子求和=n(n+1)22−(n+1)−n(n+1)(2n+1)6−1;因为从第二项开始,要减去1,痛分后得到=n(n+1)(n+2)6−n
得到最后的式子后,我们对考虑前面的贡献,显然每个数的平方或者立方都对后面造成了贡献,例如,当我们计算2的额外时,我们可以考虑它的平方4,那么2的贡献就多了(8-4+1),再考虑8,贡献多了(8-8+1),对于3也是如此,当n>3k时,贡献就多了3∗(n−3k+1),这样我们就能√(n)处理答案了
PS:打题的时候没考虑炸范围的问题,所以导致这题最后没过,记下这个锅
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 26 27 28 29 30 31 32 33 34
| #include<bits/stdc++.h> using namespace std; #define ll long long const int md = 998244353; ll ksm(ll x,ll y) { ll res=1; while(y) { if(y&1)res=(res*x)%md; y>>=1; x=(x*x)%md; } return res; } int main() { ll n; scanf("%lld",&n); int sq =ceil(sqrt(n)); ll ans = ((n%md*((n+1)%md))%md*(n%md+2)%md)%md; ans=(ans*(ksm(6,md-2)))%md; ans=(ans-n+md)%md; for(ll i=2;i*i<=n;i++) { ll x=i*i; while(x<=n) { ans=(ans+(1ll*i*(n-x+1)))%md; x*=i; } } cout<<ans<<endl; }
|
v1.3.10