1. 程式人生 > >8/14 訓練日記

8/14 訓練日記

今天主要看了容斥

容斥原理 :重要應用 求出一個數n在區間[1,m]裡面有多少個數與它互質。假設資料不超過int型。

實現過程分為兩步:

1, 求出m的質因子 並儲存在數組裡面;

2, 求出區間[1,n]裡面有多少個數與m不互質。

程式碼:

  1. #include <cstdio>

  2. #include <cmath>

  3. int p[10];//儲存質因子 int型n不會超過10個

  4. int k;//記錄質因子個數

  5. void getp(int n)//求出n的質因子

  6. {

  7. int i;

  8. k = 0;//初始化

  9. for(i = 2; i*i <= n; i++)

  10. {

  11. if(n % i == 0)

  12. {

  13. p[k++] = i;//儲存質因子

  14. while(n % i == 0)

  15. n /= i;

  16. }

  17. }

  18. if(n > 1) p[k++] = n;//本身是質數

  19. }

  20. int nop(int m)//求出區間[1,m]裡面有多少個數與n不互質

  21. {

  22. int top = 0;//佇列頂點

  23. int que[10100];

  24. int i, j, t;

  25. que[top++] = -1;//佇列陣列儲存n所有質因子任意不相同組合的乘積

  26. for(i = 0; i < k; i++)

  27. {

  28. t = top;//利於下面計算

  29. for(j = 0; j < t; j++)

  30. {

  31. que[top++] = que[j] * p[i] * (-1);//奇加偶減

  32. }

  33. }

  34. int sum = 0;//統計個數

  35. for(i = 1; i < top; i++)

  36. sum += m / que[i];

  37. return sum;

  38. }

  39. int main()

  40. {

  41. int n, m;

  42. while(scanf("%d%d", &n, &m), n||m)//求區間[1,m]內有多少個數與n互質

  43. {

  44. getp(n);

  45. printf("%d\n", m-nop(m));

  46. }

  47. return 0;

  48. }


上面的程式碼實現是很簡單的,也是很好理解的。 網上還有DFS版本,位運算版本的以及遞迴版本的,這裡再給個遞迴的(另外本人理解不太透徹),至於其它兩個有興趣的可以上網查下。

遞迴版本:

  1. #include <cstdio>

  2. #include <cmath>

  3. int p[10];//儲存質因子 int型n不會超過10個

  4. int k;//記錄質因子個數

  5. void getp(int n)//求出n的質因子

  6. {

  7. int i;

  8. k = 0;//初始化

  9. for(i = 2; i*i <= n; i++)

  10. {

  11. if(n % i == 0)

  12. {

  13. p[k++] = i;//儲存質因子

  14. while(n % i == 0)

  15. n /= i;

  16. }

  17. }

  18. if(n > 1) p[k++] = n;//本身是質數

  19. }

  20. int nop(int m, int t)//求出區間[1,m]裡面有多少個數與n不互質

  21. {

  22. int i, sum = 0;

  23. for(i = t; i < k; i++)

  24. sum += m / p[i] - nop(m/p[i],i+1);

  25. return sum;

  26. }

  27. int main()

  28. {

  29. int n, m;

  30. while(scanf("%d%d", &n, &m), n||m)//求區間[1,m]內有多少個數與n互質

  31. {

  32. getp(n);

  33. printf("%d\n", m-nop(m, 0));

  34. }

  35. return 0;

  36. }