【HDU】2841 Visible Trees

题意:n*m的格子,每个格子都种有一树,左下角坐标为(1,1)。问在(0,0)最多看到多少树。

显然,若(x,y)能被看到,那么(k*x,k*y),其中k>1都不能被看到。

因此,问题转化为求1<=x<=n且1<=y<=m有多个满足gcd(x,y)=1。

那么可以从1~n枚举x,累计1~m中与x互质的个数。

对x分解素因子,容斥一下就好了。

 1 #include
 2 #include
 3 #define MAXN 100010
 4 typedef long long LL;
 5 using namespace std;
 6 vector<int> fac[MAXN];
 7 void Init() {
 8     int i, j;
 9     for (i = 0; i < MAXN; i++)
10         fac[i].clear();
11     for (i = 2; i < MAXN; i++) {
12         if (fac[i].size())
13             continue;
14         fac[i].push_back(i);
15         for (j = 2; i * j < MAXN; j++)
16             fac[i * j].push_back(i);
17     }
18 }
19 LL Gao(int x, int &k, int t) {
20     LL res;
21     int i;
22     res = 1;
23     for (i = k = 0; x; x >>= 1, i++) {
24         if (x & 1) {
25             k++;
26             res *= fac[t][i];
27         }
28     }
29     return res;
30 }
31 LL Prime(int k, int m) {
32     int i, j, t;
33     LL ans, tmp;
34     t = (int) fac[k].size();
35     ans = 0;
36     for (i = 1; i < (1 << t); i++) {
37         tmp = Gao(i, j, k);
38         if (j & 1)
39             ans += m / tmp;
40         else
41             ans -= m / tmp;
42     }
43     return m - ans;
44 }
45 int main() {
46     int c;
47     int n, m, i;
48     LL ans;
49     Init();
50     scanf("%d", &c);
51     while (c--) {
52         scanf("%d%d", &n, &m);
53         ans = m;
54         for (i = 2; i <= n; i++)
55             ans += Prime(i, m);
56         printf("%I64d\n", ans);
57     }
58     return 0;
59 }

转载于:https://www.cnblogs.com/DrunBee/archive/2012/09/06/2673064.html

你可能感兴趣的:(【HDU】2841 Visible Trees)