洛谷P3636 曲面

链接

  https://www.luogu.org/problem/show?pid=3636

题解

  题目大意:对于所有 k[1,N] ,求满足 xyz=k 的整数 x,y,z (|x|+|y|+|z|)2 之和。
  看起来很麻烦,我用了很多种方法都不行,最后还是找对了路子。首先如果我们枚举 k 的话会很慢,所以条件可以改成:xyzN,求这样的 (x,y,z) (|x|+|y|+|z|)2 之和。忘了加一句,答案应该是对第一卦限(x>0,y>0,z>0)做完之后的结果乘以4。
  

ans=4×x=1Ny=1Nxz=1Nxy(x+y+z)2

  呃似乎很慢…可以看到对于给定的 x y,后面的 Nxyz=1(x+y+z)2 就是 (x+y+1)2+(x+y+2)2+...+(x+y+Nxy)2 ,这个就是平方和的连续一段,直接用平方和公式。设 f(n)=n(n+1)(2n+1)6 ,则答案
  
ans=4×x=1Ny=1Nx[f(x+y+Nxy)f(x+y)]

  这样是 O(N1+N2+N3+...+NN)=O(NlogN) 的。可以过60分,到这里我就卡住了,不会优化…打完T3的暴力之后又回来看,我换了一种思路。
  如果令 x<y<z ,那么结合 xyzN 的条件,可以得到 x<N3 ,咦这似乎可以降复杂度,于是继续写,得到当 x<y<z
  
ans1=x<N3y<Nx[f(x+y+Nxy)f(x+y+y)]

  (这里的 f(x+y+y) 写成 f(x+y+(y+1)1) 可能好理解些)
  那么这个肯定是 O(N3logN3) 的。
  上面是三个数字互不相同,在考虑有两个相同并且和第三个不同的,即 x=yz
  
ans2=x<N[f(x+x+Nx2)f(x+x)](x+x+x)2[if(x3N)]

  最后考虑 x=y=z
  
ans3=x=1N3(x+x+x)2

  然后
ans=4×(6ans1+3ans2+ans3)

  总的时间复杂度是 O(N)
  听说正解是杜教筛啥的,好厉害的样子…我不会

代码

#include <cstdio>
#include <algorithm>
#define mod 10007ll
#define lim 100000000000000000ll
#define ll long long
using namespace std;
ll inv[100];
inline ll f(ll n){return n*(n+1)%mod*(2*n+1)*inv[6]%mod;}
inline ll sqr(ll x){return x*x;}
inline ll pow(ll a, ll b)
{
    ll ans, t;
    for(ans=1,t=a;b;b>>=1,t=t*t%mod)if(b&1)ans=ans*t%mod;
    return ans;
}
void init()
{
    ll i;
    for(i=1;i<=10;i++)inv[i]=pow(i,mod-2)%mod;
}
ll work(ll N)
{
    ll x, y, ans=0, t;
    //x<y<z
    t=0;
    for(x=1;x*x*x<N;x++)
    {
        for(y=x+1;y<N/x/y;y++)
        {
            t+=f(x+y+(N/x/y))-f(x+y+y);
            if(t>lim)t%=mod;
        }
    }
    ans+=t*6%mod;
    //x=y!=z
    t=0;
    for(x=1;x*x<=N;x++)
    {
        t=t+f(x+x+N/x/x)-f(x+x);
        if(x*x*x<=N)t=t-sqr(x+x+x);
        if(t>lim)t%=mod;
    }
    ans+=t*3%mod;
    //x=y=z
    t=0;
    for(x=1;x*x*x<=N;x++)
    {
        t+=sqr(x+x+x);
        if(t>lim)t%=mod;
    }
    ans+=t%mod;
    return ans%mod;
}
int main()
{
    ll a, b, ans;
    scanf("%lld%lld",&a,&b);
    init();
    if(a>b){printf("0");return 0;}
    ans=work(b)-work(a-1);
    printf("%lld",(ans*4%mod+mod)%mod);
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值