机器人的项链 HDU
来源:互联网 发布:淘宝手机详情文字大小 编辑:程序博客网 时间:2024/04/29 05:59
机器人的项链 HDU - 2239
刚开始做欧拉函数的题目,先说一下欧拉函数吧。
euler(x)就是计算1~n中有多少个与n互质的个数;
公式:euler(x)=x(1-1/p1)(1-1/p2)(1-1/p3)(1-1/p4)…(1-1/pn);
具体实现两种:
//1.int euler(int n){ //返回euler(n) int res=n,a=n; for(int i=2;i*i<=a;i++) { if(a%i==0) { res=res/i*(i-1);//先进行除法是为了防止中间数据的溢出 while(a%i==0) a/=i; } } if(a>1) res=res/a*(a-1); return res;}//2,打表//筛选法打欧拉函数表 #define Max 1000001int euler[Max];void Init(){ euler[1]=1; for(int i=2;i<Max;i++) euler[i]=i; for(int i=2;i<Max;i++) if(euler[i]==i) for(int j=i;j<Max;j+=i) euler[j]=euler[j]/i*(i-1);//先进行除法是为了防止中间数据的溢出 }/*对于这个题,需要对欧拉函数进行一个简单 的“优化”。否者会超时。即先筛素数再用模板。euler (x): 1~x中互质的数的个数,*** euler(n/i): 1~n中有多少个数的最大公约数是i;
即:
int prime[maxn];bool isprime[maxn];int cnt;void Init(){ cnt=0; memset(isprime,0,sizeof isprime);ll i,j;for(i=2;i<=N;i++){if(!isprime[i])prime[cnt++]=i;for(j=0;j<cnt && i*prime[j]<=N;j++){isprime[i*prime[j]]=true;}}cnt--;isprime[1]=true;}ll euler(ll n){ll i;ll tempn=n;ll ans=n;for(i=0;i<=cnt && prime[i]*prime[i]<=n;i++){if(n%prime[i]==0){ans=ans/prime[i]*(prime[i]-1);while(tempn%prime[i]==0)tempn/=prime[i];}}if(tempn>1)ans=ans/tempn*(tempn-1);return ans;}
再说一下Polya定理:
设
是n个对象的一个置换群, 用m种颜色染图这n个对象,则不同的染色方案数为:
其中
,为的循环节数
简单来讲就是用m中颜色去染n个对象,这n个对象是环状的,求方案数。
置换:设X为一个有限集,π是X到X的一个--变换,那么称π是X上的一个置换。
比如:
{ 1 2 3 4 5 }的置换群{ (1 2 3 4 5 ) ( 2 3 4 5 1) (3 4 5 1 2) (4 5 1 2 3) (5 1 2 3 4) }
循环节:
1 2 3 4 5
3 4 1 2 5 循环节就是比较上下两个数列:如果出现上面的与下面的集合能够出现全等。
比如:上面的1->3,3->1,这就是一个循环节,同样{ 2->4,4->4},{ 5->5 },一共三个循环节。
循环节的求法:
把所有置换写出来,就能知道它们的循环节数了;
对于旋转,有c(ai) = gcd(n,i),i为转动幅度,1~n,gcd是求最大公约数。
对于 这个题:ans=sum(m^gcd(n,i))/n;
又因为n很大,所以要用欧拉函数处理,即用欧拉函数枚举n的约数 ,找到最大公约数为 i 的个数,ans=Sum(euler(n/i)*m^i)/n;
除n本来要用逆元,但是有些数的逆元不存在,所以不能用,
正确做法是枚举每个数找到ans最小值。
比如:
{ 1 2 3 4 5 }的置换群{ (1 2 3 4 5 ) ( 2 3 4 5 1) (3 4 5 1 2) (4 5 1 2 3) (5 1 2 3 4) }
循环节:
1 2 3 4 5
3 4 1 2 5 循环节就是比较上下两个数列:如果出现上面的与下面的集合能够出现全等。
比如:上面的1->3,3->1,这就是一个循环节,同样{ 2->4,4->4},{ 5->5 },一共三个循环节。
循环节的求法:
把所有置换写出来,就能知道它们的循环节数了;
对于旋转,有c(ai) = gcd(n,i),i为转动幅度,1~n,gcd是求最大公约数。
对于 这个题:ans=sum(m^gcd(n,i))/n;
又因为n很大,所以要用欧拉函数处理,即用欧拉函数枚举n的约数 ,找到最大公约数为 i 的个数,ans=Sum(euler(n/i)*m^i)/n;
除n本来要用逆元,但是有些数的逆元不存在,所以不能用,
正确做法是枚举每个数找到ans最小值。
代码:
#include<stdio.h>#include<iostream>#include<string.h>#include<string>#include<stdlib.h>#include<math.h>#include<vector>#include<list>#include<map>#include<stack>#include<queue>#include<algorithm>#include<numeric>#include<functional>#define maxn 80010using namespace std;const int MOD=9937;typedef long long ll;bool vis[maxn];int prime[maxn];int len;void Init(){ len=0; memset(vis,0,sizeof vis); for(int i=2;i<=maxn;i++) { if(!vis[i]) { prime[len++]=i; for(int j=i*2;j<=maxn;j+=i) vis[j]=1; } }}int euler(int n){ int res=n,a=n; for(int i=0;(ll)prime[i]*prime[i]<=a&&i<len;i++) { if(a%prime[i]==0) { res=res/prime[i]*(prime[i]-1); while(a%prime[i]==0) a/=prime[i]; } } if(a>1) res=res/a*(a-1); return res%MOD;}int Pow(int a,int b){ a%=MOD; int res=1; while(b) { if(b&1) res=res*a%MOD; a=a*a%MOD; b>>=1; } return res;}int main(){ int n,m; Init(); while(scanf("%d%d",&n,&m)!=EOF) { ll ans=0; for(int i=1;i<=sqrt(n)+1;i++) { if(n%i==0) { ans=(ans+euler(n/i)*Pow(m,i)%MOD)%MOD; if(i!=n/i) ans=(ans+euler(i)*Pow(m,n/i)%MOD)%MOD;// 注意n/i 的计算 } } int tot = ans; for (ans = 0; ans < MOD; ans++) if ((ll)ans*n % MOD == tot % MOD) break; printf ("%d\n", ans); } return 0;}
阅读全文
1 0
- 机器人的项链 HDU
- 【HDU】 2239 机器人的项链
- hdu 2233 机器人的旅行
- HDU ACM 2232 机器人的舞蹈
- HDU ACM 2233 机器人的旅行
- HDU 2232 机器人的舞蹈 矩阵乘法
- 串起珍珠的项链
- HH的项链(diff)
- HH的项链
- -失而复得的项链-
- 坏掉的项链
- 【USACO】坏掉的项链
- [SDOI2009]HH的项链
- BZOJ1878 HH的项链
- 【Bzoj1878】HH的项链
- 【SDOI2009】HH的项链
- Dark的项链(树链剖分)
- [P1203]坏掉的项链
- C#动态创建类和使用特性增强程序可扩展性
- uva 10237 n x n棋盘上放k个棋子 棋子不能在同一斜线上 求总类数
- java中的final修饰符
- NYOJ 1309 冰法斗神龙
- Eclipse使用中遇到的问题及其解决
- 机器人的项链 HDU
- $(window).scroll() 方法不能触发
- Linux 进程总结
- Active Learning: 一个降低深度学习时间,空间,经济成本的解决方案|CVPR 2017
- 一张图看懂字符编码
- HDU 6043 KazaQ's Socks(水~)
- 友善之臂S3C2451开发板如何用MiniTools下载裸机程序
- Mac OS下包管理器Homebrew的安装与使用
- Linux 常用命令