http://acm.hdu.edu.cn/showproblem.php?pid=6069
每次做多校的题目,基本就是切水题,切完之后就挂机(真佩服那些神犇,什么都会做),毫无进度,这个题目找到过一道和这个很类似的题目
那个题目是用莫比乌斯反演做的,看了一下代码,完全看不懂,然后就放弃了。
其实之前也想到过枚举因数,但是碰到一个问题,就是觉得质数无法打表到1e12这么多,但是其实只需要打表到1e6就可以了
因为你到了如果这个最大的值也才1e12,所以如果这个数有个大于1e6的因子的话,那么说明这个因子只有一个。因为如果有两个的话,那么它肯定大于1e12了
但是做的时候这点没有想到,都是觉得要打表打到1e12,所以没能做
然后其实看了一下题解,然后确实感觉豁然开朗
只需要枚举一下质数,看看这个区间里面的这个质数有多少个
因为$x = p_{_{1}}^{k1}*p_{2}^{k2}*.....*p_{n}^{kn}$
所以x的因子个数n =$(k_{1}+1)*(k_{2}+1)*(k_{3}+1)*.....*(k_{n}+1)$
#include <stdio.h> #define maxn 1000100 #define ll long long #define mod 998244353 bool v[maxn]; ll p[maxn],tot = 0; ll l,r,k,ans[maxn],num[maxn],n; void init() { for (int i = 2; i < maxn; i++) { if (!v[i])p[tot++] = i; for (int j = 0; j < tot&&i*p[j] < maxn; j++) { v[i*p[j]] = 1; if (i%p[j] == 0)break; } } } void Find(ll x) { for(ll i = l/x*x;i<=r;i+=x) { if(i>=l) { int cnt = 0; while(num[i-l]%x==0) { num[i-l]/=x; cnt++; //n次方 } ans[i-l] = ans[i-l]*((ll)cnt*k+1)%mod; //统计有多少个 } } } void calc() { scanf("%lld%lld%lld",&l,&r,&k); n = r - l; for(int i=0;i<=n;i++) { num[i] = i+l; ans[i] = 1; } for(int i = 0;i<tot;i++){ if((ll)p[i]*p[i]>r) break; Find(p[i]); //枚举质数 } } int main() { init(); int t; scanf("%d",&t); while(t--) { calc(); long long a = 0; for(int i =0;i<=n;i++){ if(num[i]>1) ans[i] = ans[i]*(k+1)%mod; //大于1e6的只有一个,所以乘以k+1就可以了
a = (a+ans[i])%mod; } printf("%lld ",a); } return 0; }