HDU 找新朋友(标记)
找到该数的所有因子,然后使用一个标记数组去标记为其因子为1,把其因子的倍数 (小于该数) 也标记为1,被标记的数即为其老朋友。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 using namespace std; 5 6 #define MAX 32770 7 static int flag[MAX] = {0}; 8 9 int main() 10 { 11 int t; 12 scanf("%d", &t); 13 while (t--) 14 { 15 memset(flag, 0, sizeof(flag)); 16 int n; 17 scanf("%d", &n); 18 int x = n / 2; 19 for (int i = 2; i <= x; i++) 20 { 21 if (n % i == 0) 22 { 23 flag[i] = 1; 24 for (int j = 2; i * j < n; j++) 25 { 26 flag[i * j] = 1; 27 } 28 } 29 } 30 int ans = 1; //1也是新朋友 31 for (int i = 2; i < n; i++) 32 { 33 if (flag[i] == 0) 34 ans++; 35 } 36 printf("%d\n", ans); 37 } 38 return 0; 39 }
刚开始自己的做法,找从2到n,所有与该数最大公约数不为1的数之和,最后再加上1,结果超时。。。
1 #include <cstdio> 2 3 #define MAX 32770 4 5 int gcd(int a, int b) 6 { 7 return (a % b == 0) ? b : gcd(b, a % b); 8 } 9 10 int main() 11 { 12 int t; 13 scanf("%d", &t); 14 while (t--) 15 { 16 int num = 1; 17 int n; 18 scanf("%d", &n); 19 for (int i = 2; i < n; i++) 20 { 21 if (gcd(i, n) == 1) 22 { 23 num++; 24 } 25 } 26 printf("%d\n", num); 27 } 28 29 return 0; 30 }
然后就想,在做这道题之前做了两道关于打表的题,这道题肯定也是一道打表题,然后就感觉思路被封死了,一直想生成表的方法,最后实在没有找到好的刷新表的思路,就硬生成了一张表,写完感觉就不行,这种递归太多层了,试了一下,生成表用了30多秒...如果有大神有思路,告诉一下小弟,小弟感激不尽。
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 using namespace std; 5 6 #define MAX 32770 7 static int table[MAX] = {0}; 8 9 int gcd(int a, int b) 10 { 11 return (a % b == 0) ? b : gcd(b, a % b); 12 } 13 14 void Table() 15 { 16 for (int i = 2; i < MAX; i++) 17 { 18 for (int j = 1; j < i; j++) 19 { 20 if (gcd(i, j) == 1) 21 { 22 table[i]++; 23 } 24 } 25 } 26 // cout << "over" << endl; 27 } 28 29 int main() 30 { 31 Table(); 32 int t; 33 scanf("%d", &t); 34 while (t--) 35 { 36 int n; 37 scanf("%d", &n); 38 printf("%d\n", table[n]); 39 } 40 return 0; 41 }