HDU6069(数学)

我不是女神ヾ 2022-06-11 09:36 201阅读 0赞

题目链接:hdu6069


题目大意:

  1. 给你三个数l,r,k (1lr10^12,rl10^6,1k10^7)求 :

(∑i=lrd(ik))mod998244353


题目思路:

  1. 首先我们很好想到的是枚举区间[l,r] ,然后对于每个i我们分解因子,但是这样做的复杂度是(r-l+1)*sqrt(r) 已经超时了,
  2. 所以我们要去优化分解因子,这里我们筛选出1e6内的质数,然后拿质数去枚举区间,这样就可以避免重复分解同样的因子,然后
  3. 就是怎么求d(i^k),根据约数定理得到d(i^k) = (1+x1*k)*(1+x2*k)*... x1,x2..为i分解后因子的个数,所以我们可以
  4. 用个数组保存每个i的答案最后加起来就是

AC代码:

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. const long MAXP = 1000000;
  4. long prime[MAXP] = {
  5. 0},num_prime = 0;
  6. long long d[1000005],v[1000005];
  7. int isNotPrime[MAXP] = {
  8. 1, 1};
  9. #define mod 998244353
  10. int main()
  11. {
  12. for(long i = 2 ; i < MAXP ; i ++)
  13. {
  14. if(! isNotPrime[i])
  15. prime[num_prime ++]=i;
  16. for(long j = 0 ; j < num_prime && i * prime[j] < MAXP ; j ++)
  17. {
  18. isNotPrime[i * prime[j]] = 1;
  19. if( !(i % prime[j]))
  20. break;
  21. }
  22. }
  23. int t;cin>>t;
  24. while(t--)
  25. {
  26. long long l,r,k;
  27. scanf("%lld%lld%lld",&l,&r,&k);
  28. for(long long i=0;i<r-l+1;i++)
  29. {
  30. d[i] = 1;
  31. v[i] = l+i;
  32. }
  33. long long ans = 0;
  34. long long cnt = 0;
  35. for(int i=0;i<num_prime;i++)
  36. {
  37. if(prime[i]>r)break;
  38. long long x = l/prime[i]*prime[i];
  39. if(x<l)x+=prime[i];
  40. long long y = 0;
  41. while(x+y*prime[i]<=r)
  42. {
  43. cnt++;
  44. long long xx = x+y*prime[i],cnt1 = 0;
  45. y++;
  46. int id = xx-l;
  47. while(v[id]%prime[i]==0)
  48. {
  49. cnt1++;
  50. v[id]/=prime[i];
  51. }
  52. d[id]*=(1+k*cnt1);
  53. d[id]%=mod;
  54. }
  55. }
  56. for(long long i=0;i<r-l+1;i++)
  57. {
  58. if(v[i]!=1)
  59. {
  60. ans = (ans+(d[i]*(1+k))%mod)%mod;
  61. }
  62. else
  63. {
  64. ans = (ans+d[i])%mod;
  65. }
  66. }
  67. printf("%lld\n",ans);
  68. }
  69. return 0;
  70. }

发表评论

表情:
评论列表 (有 0 条评论,201人围观)

还没有评论,来说两句吧...

相关阅读

    相关 HDU 1141(数学题)

    题意:1960年的计算机是4位处理器,1970年是8位,没过10年翻一倍,求当前年份的计算机处理器能存储的阶乘n!中n的大小。   思路:假设处理器的位数为x位,则n! <