您的位置:首页 > 大数据 > 人工智能

【2017 Multi-University Training Contest - Team 4】Counting Divisors

2017-10-04 18:44 489 查看

【Link】:http://acm.hdu.edu.cn/showproblem.php?pid=6069

【Description】

定义d(i)为数字i的因子个数;
求∑rld(ik)
其中l,r<=1012且r−l<=106

【Solution】

如果把一个数x质因数分解成p1a1∗p2a2∗...∗pnan
的形式;
可知数字x的因子个数为
(a1+1)∗(a2+1)∗...∗(an+1)
因为i还有k次方;
所以答案就是
(a1∗k+1)∗(a2∗k+1)∗...∗(an∗k+1)
需要对l..r里面所有的数字都进行质因数分解;
可以这样
先处理出2..r√之间的所有素数;
然后枚举每个素数i它在l..r之间的倍数x;
则对x 用素数i进行质因数分解,也即一直除它;
这样,就能算出来x在质因数分解的时候,素数i最后的指数是多少了;
(累乘数字x的答案就好);
记录x在进行质因数分解的时候被除剩下的数字,除的时候是用
这个记录的数字除;
最后这个数字可能会不变;
因为它本身可能就是一个素数;
所以小于r√的素数可能不是它的因子;
但是不可能还有大于r√的因子;
所以如果除剩下的数字还大于0;
答案再乘上(k+1)就好;
最后把每个数字它的答案累加起来;
(一开始可以用O(n)的素数筛求出1..n之间的所有素数);

【NumberOf WA】

many times

【Reviw】

一开始一直往O(n14)的质因数分解想了;
没想到这种方法.
判断出某个素数是某个数的因子之后,不要再记录它的因子是什么了;
直接就开始质因数分解,这样比较快;
不然会超时.

【Code】

#include <bits/stdc++.h>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define LL long long
#define rep1(i,a,b) for (int i = a;i <= b;i++)
#define rep2(i,a,b) for (int i = a;i >= b;i--)
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define ms(x,y) memset(x,y,sizeof x)
#define ri(x) scanf("%d",&x)
#define rl(x) scanf("%lld",&x)
#define rs(x) scanf("%s",x+1)
#define oi(x) printf("%d",x)
#define ol(x) printf("%lld",x)
#define Open() freopen("F:\\rush.txt","r",stdin)
#define Close() ios::sync_with_stdio(0)

typedef pair<int,int> pii;
typedef pair<LL,LL> pll;

const int dx[9] = {0,1,-1,0,0,-1,-1,1,1};
const int dy[9] = {0,0,0,-1,1,-1,1,-1,1};
const double pi = acos(-1.0);
const int N = 1e6;
const LL MOD = 998244353;

bool iszs[N+100];
vector <int> zsb;
LL num[N+100],ans[N+100];

int main(){
//Open();
//Close();
ms(iszs,true);
rep1(i,2,N)
{
if (iszs[i]) zsb.pb(i);
int len = zsb.size();
rep1(j,0,len-1)
{
int t = zsb[j];
if (i*t>N) break;
iszs[i*t] = false;
if (i%t==0) break;
}
}

int T;
ri(T);
while (T--){
LL l,r,k;
rl(l),rl(r),rl(k);
for (LL i = l;i <= r;i++)
num[i-l+1] = i,ans[i-l+1] = 1;

rep1(i,0,(int) zsb.size()-1){
LL x = zsb[i];
if (x > r) break;
LL temp = ((l-1)/x + 1)*x;
for (LL i = temp;i <= r;i+=x){
LL tot = i,cnt = 0;
while (tot%x==0){
tot/=x;
num[i-l+1]/=x;
cnt++;
}
ans[i-l+1] = ans[i-l+1]*(cnt*k+1)%MOD;
}
}

LL fans = 0;

for (LL i = l;i <= r;i++){
if (num[i-l+1]!=1){
fans = (fans + ans[i-l+1]*(k+1)%MOD)%MOD;
}else
fans = (fans + ans[i-l+1])%MOD;
}
ol(fans);puts("");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐