HDU 6134 Battlestation Operational

来源:互联网 发布:编程入门软件 编辑:程序博客网 时间:2024/06/10 21:34

题意:

求       f(n)=i=1nj=1iij[(i,j)=1]

思路:

比赛的时候不会写,看了别人的博客半天才看懂,看来理解还是不够深啊

这里就不推导了

重新对欧拉函数,莫比乌斯函数,还有那个因子数的积性有了新的理解

欧拉函数:

我们知道


由于欧拉筛法,每次我们都遍历一个素数 j
如果 n%j==0 说明 n中存在素因子j ,那么在euler[n]中已经乘过(1 - (1/j))
euler[n]   = n*(1 - (1/j))*k
euler[n*j] = n*j*(1-(1/j))*k =       euler[n]*j
如果n%j!=0 ,那么说明 n,j互素 
euler[n*j]=euler[n]*euler[j]=                euler[n]*(j-1)
 if(i%prime[j]==0)          {              euler[i*prime[j]]=euler[i]*prime[j];              break;          }          euler[i*prime[j]]=euler[i]*(prime[j]-1);



莫比乌斯函数:
同样由于欧拉筛法,每次我们都遍历一个素数 j
如果 n%j  ==0 说明 n中存在素因子j,那么u[j*n]=0;
如果 n%j!=0 说明 n中不存在素因子j ,那么u[j*n]=-u[n];
 if(i%prime[j]==0)          {              mu[i*prime[j]]=0;              break;          }          mu[i*prime[j]]=-mu[i];



因子数:
因子数=(1 + e1) * (1 + e2) * ... * (1 + ek)
如果 n%j!=0 说明 n中不存在素因子j ,j与n互素,那么d[j*n]=d[n]*(1+1);
如果 n%j  ==0 说明 n中存在素因子j,这种情况要好好想想
由于欧拉筛法,素数 j是n的最小的一个素因子
n*j=(n/(j^k))*(j^(k+1))
d[j*n] =  d[(n/(j^k))]* d[(j^(k+1))];
由于欧拉筛法,素数 j是n的最小的一个素因子
(j^k)与 n是一个一一对应的关系 
令temp[n]=(j^k);
d[j*n] =  d[   n/temp[n]    ]* (d[temp[n]]+1);
于是对于temp[n]
如果 n%j!=0 说明 n中不存在素因子j ,                                       temp[n*j]=temp[n]  * j;
如果 n%j  ==0 说明 n中存在素因子j,此时j是n*j最小的素因子      temp[n*j]=j;

 if(i%prime[j]==0)          {              temp[i*prime[j]]=prime[j]*temp[i];              d[i*prime[j]]=d[i/temp[i]]*(d[temp[i]]+1);              break;          }          temp[i*prime[j]]=prime[j];          d[i*prime[j]]=2*d[i];    

过题代码
#include<bits/stdc++.h>using namespace std;#define maxn 1000005#define mod 1000000007typedef long long ll;int prime[maxn],mu[maxn],euler[maxn],res,d[maxn],temp[maxn],ans[maxn];void mo(){    mu[1]=euler[1]=d[1]=1;    res=0;    for(int i=2;i<maxn;i++)    {      if(!temp[i])      {          temp[i]=i;          euler[i]=i-1;          mu[i]=-1;              prime[res++]=i;          d[i]=2;      }          for(int j=0;j<res&&i*prime[j]<maxn;j++)      {          if(i%prime[j]==0)          {              mu[i*prime[j]]=0;              euler[i*prime[j]]=euler[i]*prime[j];              temp[i*prime[j]]=prime[j]*temp[i];              d[i*prime[j]]=d[i/temp[i]]*(d[temp[i]]+1);              break;          }          mu[i*prime[j]]=-mu[i];          euler[i*prime[j]]=euler[i]*(prime[j]-1);          temp[i*prime[j]]=prime[j];          d[i*prime[j]]=2*d[i];      }    }       for(int i=2;i<maxn;i++)   d[i]+=d[i-1];     for(int i=1;i<maxn;i++)  for(int j=i;j<maxn;j+=i)  if(mu[j/i]!=0) ans[j]=(ans[j]+(mu[j/i]*d[i])%mod)%mod;      for(int i=1;i<maxn;i++)    ans[i]=((ans[i]+ans[i-1])%mod+euler[i]-1)%mod;    }int main(){    mo();    int n;    while(~(scanf("%d",&n)))    cout<<ans[n]<<endl;    return 0;}










阅读全文
0 0
原创粉丝点击