hdu 6069 素数

传送门

Counting Divisors

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 658    Accepted Submission(s): 219


Problem Description
In mathematics, the function  d(n)  denotes the number of divisors of positive integer  n .

For example,  d(12)=6  because  1,2,3,4,6,12  are all  12 's divisors.

In this problem, given  l,r  and  k , your task is to calculate the following thing :

(i=lrd(ik))mod998244353

 

Input
The first line of the input contains an integer  T(1T15) , denoting the number of test cases.

In each test case, there are  3  integers  l,r,k(1lr1012,rl106,1k107) .
 

Output
For each test case, print a single line containing an integer, denoting the answer.
 

Sample Input
  
  
3 1 5 1 1 10 2 1 100 3
 

Sample Output
  
  
10 48 2302
 

Source
 

Recommend
liuyiding   |   We have carefully selected several similar problems for you:   6079  6078  6077  6076  6075 
 

题意:d代表因子个数。如题。求l-r的d的因子总数

idea:设n=p_1^{c_1}p_2^{c_2}...p_m^{c_m}n=p1c1p2c2...pmcm,则d(n^k)=(kc_1+1)(kc_2+1)...(kc_m+1)d(nk)=(kc1+1)(kc2+1)...(kcm+1)

比赛时被因子和这个玩意卡哭了。一个数必定是要在根号n的复杂度内求出他的因子,但是如果这个数是素数。那么一定会消耗根号n的时间去处理。

所以如果我们能先不处理素数,先处理其他数,(因为素数的结果最后肯定是k+1),所以我们如果能把合数先处理完那么就能在很快的时间内得出答案。然而一个1e12的数,开根是1e6。那么他的因子是素数筛的素数,如果素数筛里找不到他的因子,那么这个数肯定是素数。然后对于一个区间,

如果p为倍数,如果要能被p整除,肯定得在这个区间上跳p个位置。具体看代码:

#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <map>
#include <algorithm>
using namespace std;

#define pi acos(-1)
#define endl '\n'
#define srand() srand(time(0));
#define me(x,y) memset(x,y,sizeof(x));
#define foreach(it,a) for(__typeof((a).begin()) it=(a).begin();it!=(a).end();it++)
#define close() ios::sync_with_stdio(0); cin.tie(0);
#define FOR(x,n,i) for(int i=x;i<=n;i++)
#define FOr(x,n,i) for(int i=x;i<n;i++)
#define W while
#define sgn(x) ((x) < 0 ? -1 : (x) > 0)
#define bug printf("***********\n");
typedef long long LL;
const int INF=0x3f3f3f3f;
const LL LINF=0x3f3f3f3f3f3f3f3fLL;
const int dx[]={-1,0,1,0,1,-1,-1,1};
const int dy[]={0,1,0,-1,-1,1,-1,1};
const int maxn=1000;
const int maxx=1e7+100;
const double EPS=1e-7;
const int mod=998244353;
template<class T>inline T min(T a,T b,T c) { return min(min(a,b),c);}
template<class T>inline T max(T a,T b,T c) { return max(max(a,b),c);}
template<class T>inline T min(T a,T b,T c,T d) { return min(min(a,b),min(c,d));}
template<class T>inline T max(T a,T b,T c,T d) { return max(max(a,b),max(c,d));}
inline int Scan()
{
    int Res=0,ch,Flag=0;
    if((ch=getchar())=='-')Flag=1;
    else if(ch>='0' && ch<='9')Res=ch-'0';
    while((ch=getchar())>='0'&&ch<='9')Res=Res*10+ch-'0';
    return Flag ? -Res : Res;
}

//freopen( "in.txt" , "r" , stdin );
//freopen( "data.out" , "w" , stdout );
//cerr << "run time is " << clock() << endl;

int val,vis[maxx];
LL l,r,f[maxx],d[maxx],pri[maxx];
int k;
void init()
{
    for(int i=2;i<maxx;i++)
    {
        if(!vis[i])pri[val++]=i;
        for(int j=0;j<val&&i*pri[j]<maxx;j++)
        {
            vis[i*pri[j]]=1;
            if(i%pri[j]==0)break;
        }
    }
}
void work(LL p)
{
    for(LL i=l/p*p;i<=r;i+=p)
    {
        if(i>=l)
        {
            LL cnt=0;
            while(f[i-l]%p==0)
                f[i-l]/=p,cnt++;
            d[i-l]=1LL*d[i-l]*(cnt*k+1ll)%mod;
        }
    }
}
void solve()
{
    cin>>l>>r;
    k=Scan();
    for(LL i=l;i<=r;i++)
    {
        f[i-l]=i;
        d[i-l]=1;
    }
    for(LL i=0;i<val;i++)
    {
       if(pri[i]*pri[i]>r) break;
       work(pri[i]);
    }
    LL ans=0;
    for(LL i=0;i<=(r-l);i++)
    {
        if(f[i]>1)
        {
            d[i]=1ll*d[i]*(LL)(k+1);
            d[i]%=mod;
        }
        ans=(ans+d[i])%mod;
    }
    cout<<ans<<endl;
}
int main()
{
    //freopen( "in.txt" , "r" , stdin );
   // freopen( "out.txt" , "w" , stdout );
    init();
    int t;
    t=Scan();
    while(t--)
       solve();
}


我还是太菜了。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值