HDU - 5528Count a * b 数学公式推导

HDU - 5528 Count a * b

  照着这个写的,忘了哪个大佬博客里的了

  但很多初学者,像我一样可能不懂其中一些符号的意义,还有为什么可以这样推导,所以我自己又推导了一下,并用自己的观点解释了下一些自己不懂的过程。

  至于mod264,是因为中途计算结果可能超long long,所以注意使用unsigned long long 

 1 #include<cstdio>
 2 typedef unsigned long long ull;
 3 typedef long long ll;
 4 const int N=52118;
 5 bool nop[N]={false};
 6 int pn,pri[N];
 7 void initp()
 8 {
 9     pn=0;
10     for(int i=2;i<N;i++)
11     {
12         if(!nop[i])
13             pri[pn++]=i;
14         for(int j=0;j<pn&&i*pri[j]<N;j++)
15         {
16             nop[i*pri[j]]=true;
17             if(i%pri[j]==0)
18                 break;
19         }
20     }
21 }
22 ull solve(int x)
23 {
24     ull ans1=1ull,ans2=1ull*x;
25     for(int i=0;i<pn&&pri[i]*pri[i]<=x;i++)
26     {
27         if(x%pri[i]==0)
28         {
29             ll sum=1ll;
30             int exp=0,p=1;
31             while(x%pri[i]==0)
32             {
33                 p*=pri[i];
34                 sum+=1ll*p*p;
35                 x/=pri[i];
36                 exp++;
37             }
38             ans1*=1ull*sum;
39             ans2*=1ull*(exp+1);
40         }
41     }
42     if(x>1)
43     {
44         ans1*=1ull*x*x+1;
45         ans2*=2ull;
46     }
47     return ans1-ans2;
48 }
49 int main()
50 {
51     initp();
52     int t,n;
53     scanf("%d",&t);
54     while(t--)
55     {
56         scanf("%d",&n);
57         printf("%llu\n",solve(n));
58     }
59     return 0;
60 }
项式分解
#include<cstdio>
typedef unsigned long long ull;
const int N=52118;
bool nop[N]={false};
int pn,pri[N],pa,pp[N],exp[N];
ull ans1,ans2;
void initp()
{
    pn=0;
    for(int i=2;i<N;i++)
    {
        if(!nop[i])
            pri[pn++]=i;
        for(int j=0;j<pn&&i*pri[j]<N;j++)
        {
            nop[i*pri[j]]=true;
            if(i%pri[j]==0)
                break;
        }
    }
}
void getFac(int x)
{
    pa=0;
    for(int i=0;i<pn&&pri[i]*pri[i]<=x;i++)
    {
        if(x%pri[i]==0)
        {
            pp[pa]=pri[i];
            exp[pa]=0;
            while(x%pri[i]==0)
            {
                x/=pri[i];
                exp[pa]++;
            }
            pa++;
        }
    }
    if(x>1)
    {
        pp[pa]=x;
        exp[pa++]=1;
    }
}
void dfs(int pos,int xx)
{
    if(pos>=pa)
    {
        ans1+=1ull*xx*xx;
        return ;
    }
    dfs(pos+1,xx);
    for(int i=0,p=1;i<exp[pos];i++)
    {
        p*=pp[pos];
        dfs(pos+1,xx*p);
    }
}
ull solve(int x)
{
    ans1=0ull;
    ans2=1ull*x;
    getFac(x);
    dfs(0,1);
    for(int i=0;i<pa;i++)
        ans2*=1ull*(exp[i]+1);
    return ans1-ans2;
}
int main()
{
    initp();
    int t,n;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        printf("%llu\n",solve(n));
    }
    return 0;
}
唯一分解

 

转载于:https://www.cnblogs.com/LMCC1108/p/11098527.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值