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 }

 

 

 

posted @ 2012-09-08 20:51  Naix_x  阅读(628)  评论(0编辑  收藏  举报