HDU 2239 机器人的项链(Polya+快速幂模+欧拉函数)

题目链接

今天郁闷啊,网络赛在打酱油,就一个题可以贪心可以搞,暴搜一下,TLE,贪心一下WA,直接没心情再去做了,虽然题目描述也有点问题,但是主要还是自己没有状态啊。。。日子还是要继续,明天继续加油!这个题目上午做的,同样也是很郁闷。。。

题目思路:很明显的polya,每隔一个置换的种数是m^gcd(i,n),所以要用到欧拉函数和快速幂模,本来这样准备开始写的,想了想还需要除以n,除法取模啊,找各种资料啊,找到几个关于分数取模的资料,先学习一下。。。然后发现需要扩展欧几里得。。。用扩展欧几里得求逆元,逆元貌似离散里学过(忘了),然后把这个除法就变成乘法了,a*n+b*M = 1扩展欧几里得求出a,取一下正,然后交上发现WA,检查了一下,各个地方都没错啊,找了一下题解 ,原来从0-M-1枚举一下,满足i*n %M = ans % M就可以求出最后结果。。。

知道了算法了,但是离着做对还差很远很远。。。之后我又遇到的问题:

1.欧拉函数模版效率很低。TLE,之后换了一个先筛素数,然后再判断的。

2.在中间很多细节,写的搓了,就TLE,比如不要用i*i <= n而是要先sqrt(n),前者效率低死了。

3.全局变量不要乱用,其实我也不知道是否影响效率。。。这个题我用了全局变量存sqrt(n),就超时了。。。

4.中间溢出,最后枚举i*n会溢出,想想就知道会溢出啊,真SB了,会导致WA,不知错了多少次。。。

每一个都是细节问题,这些都是编码时候的习惯问题,不注意小问题,在遇到很卡时间的题目,这些细节会TLE到死啊。。。

 1 #include <iostream>

 2 #include <cstdio>

 3 #include <cstring>

 4 #include <cmath>

 5 #define M 9937

 6 #define ll __int64

 7 using namespace std;

 8 int num;

 9 int o[60001],prim[5001];

10 int fastmod(int a,int b)

11 {

12     int ans = 1;

13     while(b)

14     {

15         if(b&1)

16             ans = a*ans%M;

17         a = (a%M)*(a%M)%M;

18         b = b >> 1;

19     }

20     return ans;

21 }

22 int euler(int n)

23 {

24     int i,ans = n,m = (int)sqrt(n + 0.5);

25     for(i = 1; i <= num-1&&prim[i] <= m; i ++)

26     {

27         if(n%prim[i] == 0)

28         {

29             ans = ans/prim[i]*(prim[i]-1);

30             while(n%prim[i] == 0) n = n/prim[i];

31         }

32     }

33     if(n > 1) ans = ans/n*(n-1);

34     return ans%M;

35 }

36 int main()

37 {

38     int n,m,i,j,ans;

39     m = 60000;

40     num = 1;

41     for(i = 2; i <= m; i ++)

42     {

43         if(!o[i])

44         {

45             prim[num ++] = i;

46             for(j = i+i; j <= m; j += i)

47             {

48                 o[j] = 1;

49             }

50         }

51     }

52     while(scanf("%d%d",&n,&m)!=EOF)

53     {

54         ans = 0;

55         j = (int)sqrt(n + 0.5);

56         for(i = 1; i <= j; i ++)

57         {

58             if(n % i == 0)

59             {

60                 ans = (ans + euler(n/i)*fastmod(m,i)%M)%M;

61                 if(i != n/i)

62                 ans = (ans + euler(i)*fastmod(m,n/i)%M)%M;

63             }

64         }

65         for (i = 0; i < M; i++)

66         if ((ll)i*n % M == ans % M)//注意溢出

67                 break;

68         printf("%d\n", i);

69     }

70     return 0;

71 }

 

 

 

你可能感兴趣的:(HDU)