题目链接:http://codeforces.com/problemset/problem/340/A

这道题目理解不难,就是在[a, b]区间内,找出同时能够被x和y整除的个数。第一次想当然的开了两个2·109的数组,分别标记能被x和y的数字,内存受不了,返回CE。仔细想了下,开这么大的一个数组没有必要,直接在[a, b]枚举每一个数,能够同时整除x和y的数就统计下来,过了PT,然而很快就被hacked(还是第一次遇到的= =,不过也好,能帮助养成严谨的思维);  第三次,稍稍改良了算法,求x和y的最小公倍数,在[a, b]的范围内累加最小公倍数的个数,直到大于b为止,然而没考虑到最小公倍数有可能小于a,于是wa。第四次,改正这个错误后,再次PT,然后又被hacked。一题被hacked两次,前无古人,后无来者啊~~~彻底绝望,不知道哪里有错......第二天再做,重交被hacked的代码(比赛中貌似被hacked的数据没有给出的)TLE,算法太差啦!!!估计被hacked的原因就是如此吧。

      说了那么多废话,步入正题。

2·109,数据量太大!不优化肯定过不了!由于是要统计同时被x和y整除的个数,那么符合条件的数肯定满足: 1 * M,2 * M,3 * M,......N * M(M表示x和y的最小公倍数)。问题就转化为在[a, b]中找到有多少个M。我的做法是,从a往后开始枚举,直到遇上第一个能同时被x和y整除的数(假设为 i );接着从b往前开始枚举,也是直到遇上第一个能同时被x和y整除的数(假设为 j )。最后的结果就是 ( j - i ) / 最小公倍数 + 1  。 这个算式的意思为:j / 最小公倍数:[1, b]之前有多少个能同时整除x和y的数,i / 最小公倍数:[1, a]之前有多少个能同时整除x和y的数,+1是因为相减之后大于等于a的第一个能同时整除x和y的数实质是没有统计的。

     



1 #include <iostream>
 2 #include <stdio.h>
 3 #include <stdlib.h>
 4 using namespace std;
 5 
 6 int gcd(int x, int y)     // 求最小公倍数
 7 {
 8     while (x != y)
 9     {
10         if (x > y)
11             x = x - y;
12         else
13             y = y - x;
14     }
15     return x;
16 }
17 
18 int main()
19 {
20     int x, y, a, b, i;
21     while (scanf("%d%d%d%d", &x, &y, &a, &b) != EOF)
22     {
23         int temp = x / gcd(x, y) * y;
24 //        printf("temp = %d\n", temp);
25         i = (a > temp ? a : temp);   // i 保证要在[a, b]区间内,以便后面的枚举操作
26         while (i % x || i % y)       // 找出第一个在[a, b]区间中能同时整除x和y的数
27             i++;
28 //        printf("i = %d\n", i);
29         while (b % x || b % y)    // 找出最后一个在[a, b]区间中能同时整除x和y的数
30             b--;
31 //        printf("b = %d\n", b);
32         printf("%d\n", (b - i) / temp + 1);
33     }
34     return 0;
35 }