NOIP提高组【JZOJ4782】Math

Description

这里写图片描述

Data Constraint

这里写图片描述

Solution

考虑到是 (1)mj=1d(ij) ,所以我们要考虑 mj=1d(ij) 的奇偶性。很显然,只有当i* j为完全平方数时,d(i* j) Mod2 才为1,其余 Mod2 后都为0。我们分解质因数设i= ap11 ap22 …… apkk ,设p表示当p*i使p *i为完全平方数时,p最小的值为多少。我们设p= ab11 ab22 …… abkk 那么显然p要使每一个p[i]+b[i]均为偶数,且b[i]尽量小。所以,当p[i]为奇数时,b[i]就为1,当p[i]为偶数时,b[i]就为0。那么我们就可以很快算出p的值了。

得到p后,我们考虑要怎样的j才时i*j为完全平方数。那么显然j=p* q2 ,q为任意数且p* q2 <=m。那么我们可以发现q的取值个数为 m/p 。所以,我们只要判断一下 m/p 的奇偶性。 m/p 为奇数则答案+1,否则答案-1。那么,这道题我们就可以用O(N* N )的时间看似解决了。

但其实,这会超时……(N<= 107 )。

问题就出在计算p上。我们要计算一个数的的指数为奇数的的质因子的连乘时是O( N )的。所以我们必须用更高级的算法!

对,就是线性筛。

设一个数i的指数为奇数的质因子的连乘是f[i],那么对于一个质数,它的f值显然是i。那么对于一个i*d[k] (d[k]表示小于等于i的质数),当i不是d[k]的倍数时,表明i中不含有d[k]这个因子,那么f[i *d[k]]显然等于f[i] *d[k]。当i是d[k]的倍数时,我们还要考虑f[i]中是否已经含有d[k]。(因为不是i是d[k]的倍数并不能说明d[k]在i中的指数为奇数!)假设f[i]中已经含有d[k],那么f[i *d[k]]中则要把d[k]删去,即f[i *d[k]]=f[i]/d[k],否则f[i *d[k]]中则要把d[k]加上,即f[i *d[k]]=f[i] *d[k]。

最后O(N)扫一遍f统计一下答案即可。总时间复杂度为O(N)。(看起来解释很复杂,其实代码很短的……)

代码

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn=10000007;
int f[maxn],n,i,t,j,k,l,x,y,z;
ll m,d[maxn],p,ans;
bool bz[maxn],bz1;
int main(){
//  freopen("data.in","r",stdin);
    scanf("%d%lld",&n,&m);
    f[1]=1;
    for (i=2;i<=n;i++){
        if (!bz[i]) d[++d[0]]=i,f[i]=i;
        for (k=1;k<=d[0];k++){
            if (i*d[k]>n) break;bz[i*d[k]]=true;
            if (i%d[k]) f[i*d[k]]=f[i]*d[k];
            else{
                if (f[i]%d[k])f[i*d[k]]=f[i]*d[k];
                else f[i*d[k]]=f[i]/d[k];
                break;
            }
        }
    }
    for (i=1;i<=n;i++){
        t=sqrt(m/f[i]);
        if (t%2) ans--;
        else ans++;
    }
    printf("%d\n",ans);
}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值