HDU 6134 Battlestation Operational

題意:

求       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 1000000007
typedef 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;
}










發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章