洛谷P1072 Hankson的趣味题

这是个NOIP原题...

题意:

给定 a b c d 求 gcd(a, x) = b && lcm(c, x) = d 的x的个数。

可以发现一个朴素算法是从b到d枚举,期望得分50分。

(为什么lyd大佬的暴力就是90...)

有个要点就是所求的x必定为d的约数。

然后根据lcm和gcd的性质,拆成质因数。

x的每个质因数个数是有范围的,可以求出来。

然后乘起来就行了。

注意要分类讨论,别用书上写的,有毒。

  1 #include <cstdio>
  2 const int N = 100010;
  3 
  4 int p[N], top;
  5 bool vis[N];
  6 
  7 inline void getp(int b) {
  8     for(int i = 2; i <= b; i++) {
  9         if(!vis[i]) {
 10             p[++top] = i;
 11         }
 12         for(int j = 1; j <= top && i * p[j] <= b; j++) {
 13             vis[i * p[j]] = 1;
 14             if(i % p[j] == 0) {
 15                 break;
 16             }
 17         }
 18     }
 19     return;
 20 }
 21 
 22 inline void clear() {
 23 
 24     return;
 25 }
 26 
 27 inline int getcnt(int pr, int a) {
 28     if(a % pr) {
 29         return 0;
 30     }
 31     int ans = 1;
 32     a /= pr;
 33     while(a % pr == 0) {
 34         ans++;
 35         a /= pr;
 36     }
 37     return ans;
 38 }
 39 
 40 inline void solve() {
 41     int a, b, c, d;
 42     scanf("%d%d%d%d", &a, &b, &c, &d);
 43     int d1 = d, ans = 1;
 44     int ta, tb, tc, td;
 45     for(int i = 1; i <= top && p[i] <= d1; i++) {
 46         if(d1 % p[i]) {
 47             continue;
 48         }
 49         td = 1;
 50         d1 /= p[i];
 51         while(d1 % p[i] == 0) {
 52             d1 /= p[i];
 53             td++;
 54         }
 55         ta = getcnt(p[i], a);
 56         tb = getcnt(p[i], b);
 57         tc = getcnt(p[i], c);
 58         if(tc < td) { // ans = td
 59             if((ta > tb && tb == td) || (ta == tb && tb <= td)) {
 60                 ;
 61             }
 62             else {
 63                 printf("0\n");
 64                 return;
 65             }
 66         }
 67         else if(tc == td) { // ans <= td
 68             if(ta > tb && tb <= td) {
 69                 ;
 70             }
 71             else if(ta == tb && tb <= td) {
 72                 ans *= (td - tb + 1);
 73             }
 74             else {
 75                 printf("0\n");
 76                 return;
 77             }
 78         }
 79     }
 80     if(d1 > 1) {
 81         td = 1;
 82         ta = getcnt(d1, a);
 83         tb = getcnt(d1, b);
 84         tc = getcnt(d1, c);
 85         if(tc < td) { // ans = td
 86             if((ta > tb && tb == td) || (ta == tb && tb <= td)) {
 87                 ;
 88             }
 89             else {
 90                 printf("0\n");
 91                 return;
 92             }
 93         }
 94         else if(tc == td) { // ans <= td
 95             if(ta > tb && tb <= td) {
 96                 ;
 97             }
 98             else if(ta == tb && tb <= td) {
 99                 ans *= (td - tb + 1);
100             }
101             else {
102                 printf("0\n");
103                 return;
104             }
105         }
106     }
107     printf("%d\n", ans);
108     return;
109 }
110 
111 int main() {
112     getp(100000);
113     int T;
114     scanf("%d", &T);
115     while(T--) {
116         solve();
117         if(T) {
118             clear();
119         }
120     }
121 
122     return 0;
123 }
AC代码

 

posted @ 2018-08-30 10:21  garage  阅读(72)  评论(0编辑  收藏  举报