BZOJ 2154 Crash的数字表格 BZOJ 2693 jzptab

题目链接

https://lydsy.com/JudgeOnline/problem.php?id=2154

https://lydsy.com/JudgeOnline/problem.php?id=2693

题解

∑ i = 1 n ∑ j = 1 m l c m ( i , j ) = ∑ i = 1 n ∑ j = 1 m i j gcd ⁡ ( i , j ) = ∑ T = 1 min ⁡ ( n , m ) S ( ⌊ n T ⌋ , ⌊ m T ⌋ ) T ∑ d ∣ T μ ( d ) d \begin{aligned} & \sum_{i=1}^n \sum_{j=1}^m \mathrm{lcm}(i,j)\\ = & \sum_{i=1}^n \sum_{j=1}^m \frac{ij}{\gcd(i,j)}\\ = & \sum_{T=1}^{\min(n,m)}S(\lfloor\frac{n}{T}\rfloor,\lfloor\frac{m}{T}\rfloor)T\sum_{d|T}\mu(d)d \end{aligned} ==i=1nj=1mlcm(i,j)i=1nj=1mgcd(i,j)ijT=1min(n,m)S(Tn,Tm)TdTμ(d)d

其中
S ( x , y ) = ∑ i = 1 x ∑ j = 1 y i j = x ( x + 1 ) 2 y ( y + 1 ) 2 \begin{aligned} S(x,y)= & \sum_{i=1}^x \sum_{j=1}^y ij\\ = & \frac{x(x+1)}{2}\frac{y(y+1)}{2} \end{aligned} S(x,y)==i=1xj=1yij2x(x+1)2y(y+1)
考虑
g ( T ) = T ∑ d ∣ T μ ( d ) d g(T)= T\sum_{d|T}\mu(d) d g(T)=TdTμ(d)d
满足以下条件
g ( T ) = { 1 T = 1 T ( 1 − T ) T ∈ P g ( p T ) = { g ( p ) g ( T ) p ∈ P , p ∤ T p g ( T ) p ∈ P , p ∣ T g(T)= \begin{cases} 1 & T=1\\ T(1-T) & T\in \mathbb P \end{cases}\\ g(pT)= \begin{cases} g(p)g(T) & p\in \mathbb P,p\nmid T\\ pg(T) & p\in \mathbb P,p\mid T \end{cases} g(T)={1T(1T)T=1TPg(pT)={g(p)g(T)pg(T)pP,pTpP,pT
因此可以线筛求出 g g g,答案可以整除分块。

代码

BZOJ 2154

#include <cstdio>
#include <algorithm>

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=10000000;
const int mod=20101009;

int p[maxn+10],prime[maxn+10],cnt,f[maxn+10],sum[maxn+10];

int getprime()
{
  p[1]=1;
  f[1]=1;
  for(int i=2; i<=maxn; ++i)
    {
      if(!p[i])
        {
          prime[++cnt]=i;
          f[i]=1-i;
        }
      for(int j=1; (j<=cnt)&&(i*prime[j]<=maxn); ++j)
        {
          p[i*prime[j]]=1;
          if(i%prime[j]==0)
            {
              f[i*prime[j]]=f[i];
              break;
            }
          f[i*prime[j]]=1ll*f[i]*(mod+1-prime[j])%mod;
        }
    }
  for(int i=1; i<=maxn; ++i)
    {
      sum[i]=(sum[i-1]+1ll*f[i]*i)%mod;
    }
  return 0;
}

int n,m,ans;

int S(int x)
{
  return (1ll*x*(x+1)/2)%mod;
}

int main()
{
  getprime();
  n=read();
  m=read();
  for(int l=1,r; l<=std::min(n,m); l=r+1)
    {
      r=std::min(n/(n/l),m/(m/l));
      ans=(ans+1ll*(sum[r]-sum[l-1]+mod)*S(n/l)%mod*S(m/l))%mod;
    }
  printf("%d\n",ans);
  return 0;
}

BZOJ 2693

#include <cstdio>
#include <algorithm>

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=10000000;
const int mod=100000009;

int p[maxn+10],prime[maxn+10],cnt,f[maxn+10],sum[maxn+10];

int getprime()
{
  p[1]=1;
  f[1]=1;
  for(int i=2; i<=maxn; ++i)
    {
      if(!p[i])
        {
          prime[++cnt]=i;
          f[i]=1-i;
        }
      for(int j=1; (j<=cnt)&&(i*prime[j]<=maxn); ++j)
        {
          p[i*prime[j]]=1;
          if(i%prime[j]==0)
            {
              f[i*prime[j]]=f[i];
              break;
            }
          f[i*prime[j]]=1ll*f[i]*(mod+1-prime[j])%mod;
        }
    }
  for(int i=1; i<=maxn; ++i)
    {
      sum[i]=(sum[i-1]+1ll*f[i]*i)%mod;
    }
  return 0;
}

int T,n,m,ans;

int S(int x)
{
  return (1ll*x*(x+1)/2)%mod;
}

int main()
{
  getprime();
  T=read();
  while(T--)
    {
      n=read();
      m=read();
      ans=0;
      for(int l=1,r; l<=std::min(n,m); l=r+1)
        {
          r=std::min(n/(n/l),m/(m/l));
          ans=(ans+1ll*(sum[r]-sum[l-1]+mod)*S(n/l)%mod*S(m/l))%mod;
        }
      printf("%d\n",ans);
    }
  return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值