UVA10820 Send a Table

嘟嘟嘟

【欧拉函数】

 

大致题意:如果知道f(a, b),就可以求出f(a * k, b * k)。现给出一个n,求至少需要知道几个二元组(a, b),使所有的f(x, y)都能求出来。(1 <= x, y <= n)

 

首先能确定的是gcd(a, b) = 1。不妨假设b >= a,那么如果b一定,至少需要phi(b)个a,才能知道所有的f(a * k, b * k)。令dp[n]表示这种情况下的答案,则dp[n] = ∑phi[i] (1 <= i <= n)。

上述是在a <= b的条件下得出的,如果没有这个条件,那么dp'[n] = dp[n] * 2 - 1。因为对于f(1, 1)只用求一遍。

总结一下,O(nlogn)预处理欧拉函数(当然线性的更好了)和前缀和,然后O(1)询问。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<cmath>
 5 #include<cstring>
 6 #include<cstdlib>
 7 #include<cctype>
 8 #include<stack>
 9 #include<queue>
10 #include<vector>
11 using namespace std;
12 #define enter puts("")
13 #define space putchar(' ')
14 #define Mem(a, x) memset(a, x, sizeof(a))
15 #define rg register
16 typedef long long ll;
17 typedef double db;
18 const int INF = 0x3f3f3f3f;
19 const db eps = 1e-8;
20 const int maxn = 5e4 + 5;
21 inline ll read()
22 {
23   ll ans = 0;
24   char ch = getchar(), las = ' ';
25   while(!isdigit(ch)) las = ch, ch = getchar();
26   while(isdigit(ch)) ans = ans * 10 + ch - '0', ch = getchar();
27   if(las == '-') ans = -ans;
28   return ans;
29 }
30 inline void write(ll x)
31 {
32   if(x < 0) putchar('-'), x = -x;
33   if(x >= 10) write(x / 10);
34   putchar(x % 10 + '0');
35 }
36 
37 int n, phi[maxn], sum[maxn];
38 
39 void euler()
40 {
41   for(int i = 1; i < maxn; ++i) phi[i] = i;
42   for(int i = 2; i < maxn; ++i) if(phi[i] == i)
43     for(int j = i; j < maxn; j += i)
44       phi[j] = phi[j] / i * (i - 1);
45   for(int i = 1; i < maxn; ++i) sum[i] = sum[i - 1] + phi[i];
46 }
47 
48 int main()
49 {
50   euler();
51   while(scanf("%d", &n) && n)
52       write((sum[n] << 1) - 1), enter;
53   return 0;
54 }
View Code

 

posted @ 2018-10-08 15:30  mrclr  阅读(133)  评论(0编辑  收藏  举报