洛谷 1072 Hankson 的趣味题——质因数界限讨论

题目:https://www.luogu.org/problemnew/show/P1072

思路是把每个数质因数分解,答案对于每个质因数的次数有选择的区间,通过这个计算。

指数的限制就是上限是b1,下限是a1;a0-a1后有剩余的自己不能有;b1-b0有剩余的自己不能剩(即必须满上限)。

分解质因数用了那个好像是 O( n^(1/4) ) 的方法。其实如果给的都是大质数是不是会被卡?

然后写了无比冗长的代码。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=35;
int T,a0,a1,b0,b1,p[N],tot,hi[N],lo[N],hi2[N],lo2[N],lm[N],ans;
bool flag=0;
int rdn()
{
  int ret=0;bool fx=1;char ch=getchar();
  while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();}
  while(ch>='0'&&ch<='9') ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar();
  return fx?ret:-ret;
}
int main()
{
  T=rdn();
  while(T--)
    {
      a0=rdn(); a1=rdn(); b0=rdn(); b1=rdn();
      int n=b1; tot=0;//limit
      for(int i=2;i*i<=n;i++)
    {
      if(n%i==0)
        {
          p[++tot]=i;lo[tot]=hi[tot]=lo2[tot]=hi2[tot]=0;
          while(n%i==0)n/=i,hi[tot]++;
          hi2[tot]=hi[tot];
        }
    }
      if(n>1)
    {
      p[++tot]=n;lo[tot]=hi[tot]=lo2[tot]=hi2[tot]=0;
      hi[tot]=hi2[tot]=1;
    }

      flag=0;
      n=a1; int p0=1;//bottom
      for(int i=2;i*i<=n;i++)
    if(n%i==0)
      {
        int d=0;
        while(n%i==0)n/=i,d++;
        while(p0<tot&&p[p0]<i)p0++;
        if(p[p0]!=i){flag=1;break;}
        lo[p0]=d;
      }
      if(flag){puts("0");continue;}
      if(n>1)
    {
      while(p0<tot&&p[p0]<n)p0++;
      if(p[p0]==n)
        lo[p0]=1;
    }

      flag=0;
      for(int i=1;i<=tot;i++)if(hi[i]<lo[i]){flag=1;break;}
      if(flag){puts("0");continue;}
      
      n=b0; p0=1;
      for(int i=2;i*i<=n;i++)
    {
      if(n%i==0)
        {
          int d=0;
          while(n%i==0)n/=i,d++;
          while(p0<tot&&p[p0]<i)p0++;
          if(p[p0]!=i)continue;
          lo2[p0]=d;//can't leave
        }
    }
      if(n>1)
    {
      while(p0<tot&&p[p0]<n)p0++;
      if(p[p0]==n) lo2[p0]=1;
    }
      for(int i=1;i<=tot;i++)
    {
      int d=hi[i]-lo2[i];
      if(d) lo2[i]=hi[i]; else lo2[i]=0;
    }
      
      n=a0; p0=1;
      for(int i=2;i*i<=n;i++)
    {
      if(n%i==0)
        {
          int d=0;
          while(n%i==0)n/=i,d++;
          while(p0<tot&&p[p0]<i)p0++;
          if(p[p0]!=i)continue;
          if(d>lo[p0])hi2[p0]=lo[p0];//can't exist
        }
    }
      if(n>1)
    {
      while(p0<tot&&p[p0]<n)p0++;
      if(p[p0]==n)
        if(1>lo[p0])hi2[p0]=lo[p0];
    }

      for(int i=1;i<=tot;i++)
    hi[i]=min(hi[i],hi2[i]),lo[i]=max(lo[i],lo2[i]);
      ans=1; flag=1;
      for(int i=1;i<=tot;i++)
    {
      if(lo[i]>hi[i]){flag=0;break;}
      ans*=hi[i]-lo[i]+1;
    }
      printf("%d\n",flag?ans:0);
    }
  return 0;
}

 

posted on 2018-10-09 18:54  Narh  阅读(241)  评论(0编辑  收藏  举报

导航