LightOJ 1341 Aladdin and the Flying Carpet

来源:互联网 发布:贴吧发帖软件 编辑:程序博客网 时间:2024/05/22 14:54

题意:给出整数 a 和 b ,求区间[b, a] 内的 a 的约数对的个数,a 的约数对(比如[2, 3] 与 [3, 2] 为同一对)。

分析:

这道题应用算数基本定理。

算数基本定理:

(1)一个大于1的正整数N,如果它的标准分解式为:
  

那么它的正因数个数为
  

(2) 它的全体正因数之和为
  

  
时就称N为完全数。 是否存在奇完全数,是一个至今未解决之猜想。
(3) 利用算术基本定理可以重新定义整数a和b的最大公因子
  
和最小公倍数
  
, 并证明
  

(4)此外还可证明根号2是无理数等等。
(5)证明素数个数无限。
用到定理1(唯一分解定理)。求出正因数的个数,然后再除以2,便是对数的个数,最后再暴力求解出[1,b]中 a 的正因数个数,相减便是答案!
代码:

#include <cstdio>  #include <cstring>  #include <cmath>#include <iostream>  #include <algorithm>  using namespace std;  #define maxn 1000010  #define LL long long  LL prim[maxn], p[maxn];  int k;  void find_prim()  {      k = 0;      for(LL i = 2; i <= maxn; i++)      {          if(!p[i])          {              prim[k++] = i;              for(LL j = i+i; j <= maxn; j+=i)              {                  p[j] = 1;              }          }      }  }  LL cont(LL a)  {      LL s = 1;      if(a == 0)      {          return 0;      }      LL tt = 0;      LL i = 0;      while(prim[i] < a && i < k)      {          tt = 0;          if(a%prim[i] == 0)          {              while(a%prim[i] == 0)              {                  a /= prim[i];                  tt++;              }          }          s *= tt+1;          i++;      }      if(a > 1)      {          s *= 1+1;//一次      }      return s;  }  int main()  {      LL a, b;      int t;      int kase = 1;      find_prim();      scanf("%d",&t);      while(t--)      {          scanf("%lld%lld", &a, &b);          int cnt = 0;          LL num = 0, ans;          if(b >= sqrt(a))              ans = 0;        // b大小限定          else          {              for(LL i = 1; i < b; i++) //暴力枚举[1, b]中a的约数              {                  if(a%i == 0)                  {                      cnt++;                  }              }              num = cont(a)/2;              ans = num - cnt;          }          printf("Case %d: %lld\n", kase++, ans);      }      return 0;  }


原创粉丝点击