题目链接
https://lydsy.com/JudgeOnline/problem.php?id=3512
题解
考虑枚举,定义
假设
令
那么
反演得到
可以递归求解。
事实上,由于每次递归,因此只需要最开始提出,后面的必定。
代码
#include <map>
#include <cstdio>
int read()
{
  int x=0,f=1;
  char ch=getchar();
  while((ch<'0')||(ch>'9'))
    {
      if(ch=='-')
        {
          f=-f;
        }
      ch=getchar();
    }
  while((ch>='0')&&(ch<='9'))
    {
      x=x*10+ch-'0';
      ch=getchar();
    }
  return x*f;
}
const int maxn=1000000;
const int maxm=100000;
const int mod=1000000007;
int p[maxn+10],prime[maxn+10],cnt,mu[maxn+10],phi[maxn+10],last[maxm+10],sum[maxn+10];
int getprime()
{
  p[1]=phi[1]=mu[1]=1;
  for(int i=2; i<=maxn; ++i)
    {
      if(!p[i])
        {
          prime[++cnt]=i;
          phi[i]=i-1;
          mu[i]=-1;
        }
      for(int j=1; (j<=cnt)&&(i*prime[j]<=maxn); ++j)
        {
          int x=i*prime[j];
          p[x]=1;
          if(i%prime[j]==0)
            {
              mu[x]=0;
              phi[x]=phi[i]*prime[j];
              break;
            }
          mu[x]=-mu[i];
          phi[x]=phi[i]*(prime[j]-1);
        }
    }
  for(int i=1; i<=maxm; ++i)
    {
      if(mu[i])
        {
          for(int j=i; j<=maxm; j+=i)
            {
              last[j]=i;
            }
        }
    }
  for(int i=1; i<=maxn; ++i)
    {
      sum[i]=sum[i-1]+phi[i];
      if(sum[i]>=mod)
        {
          sum[i]-=mod;
        }
    }
  return 0;
}
std::map<int,int> mp;
int getphi(int n)
{
  if(n<=maxn)
    {
      return sum[n];
    }
  if(mp.count(n))
    {
      return mp[n];
    }
  int res=(1ll*n*(n+1)/2)%mod;
  for(int l=2,r; l<=n; l=r+1)
    {
      r=n/(n/l);
      res=(res-1ll*(r-l+1)*getphi(n/l))%mod;
    }
  if(res<0)
    {
      res+=mod;
    }
  return mp[n]=res;
}
struct data
{
  int n,m;
  data(int _n=0,int _m=0):n(_n),m(_m){}
  bool operator <(const data &oth) const
  {
    return (n==oth.n)?(m<oth.m):(n<oth.n);
  }
};
std::map<data,int> mf;
int F(int n,int m)
{
  if(m==0)
    {
      return 0;
    }
  if(n==1)
    {
      return getphi(m);
    }
  data d(n,m);
  if(mf.count(d))
    {
      return mf[d];
    }
  int ans=0;
  for(int i=1; i*i<=n; ++i)
    {
      if(n%i!=0)
        {
          continue;
        }
      ans=(ans+1ll*phi[n/i]*F(i,m/i))%mod;
      if(i*i!=n)
        {
          ans=(ans+1ll*phi[i]*F(n/i,m/(n/i)))%mod;
        }
    }
  return mf[d]=ans;
}
int n,m;
int main()
{
  getprime();
  n=read();
  m=read();
  int ans=0;
  for(int i=1; i<=n; ++i)
    {
      ans=(ans+1ll*(i/last[i])*F(last[i],m))%mod;
    }
  printf("%d\n",ans);
  return 0;
}
 
                    
                 
 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号