题意:有三种颜色和n个珠子,让你求圆形的珠链经过旋转和翻转或本质不一样的总数。
分析:这个和poj2409几乎是一样的,只是本只有三种颜色,解法是一样的。。。要是不理解就看看本站的poj2409!!
解法一:
#include<iostream> #include<cmath> using namespace std; double ans; int n; int gcd(int a, int b) { if(b == 0) return a; return gcd(b, a%b); } int main() { int i,j,k; while(scanf("%d",&n) && n!=-1) { if(n==0) { printf("0/n"); continue; } ans = 0.0; for(i=0; i<n; i++) ans += pow(3.0,gcd(n,i)); //只有3种颜色、和poj2409几乎一样的。、 if(n & 1) { for(i=0; i<n; i++) ans += pow(3*1.0, (n+1)/2); } else { for(i=0; i<n/2; i++) { ans += pow(3*1.0, (n+2)/2); ans += pow(3*1.0, n/2); } } printf("%.0lf/n",ans/(2*n)); } return 0; }
解法二:很补素的求法,但是最好还是用第一种解法,出现高精度好处理点。
#include<iostream> #include<cmath> using namespace std; #define M 25 int g[M], flag[M]; int p,ans,n; double res = 0.0; int main() { int i,j,k; while(scanf("%d",&n)) { if(n==-1) break; if(n==0) { printf("0/n"); continue; } res = 0.0; memset(g,0,sizeof(g)); for(i=0; i<n; i++) //这个循环包含了N次旋转置换和N次翻转置换 { memset(flag,0,sizeof(flag)); for(j=0; j<n; j++) //每次旋转置换后的结果,, g[j] = (i+j) % n; //ans = 0; for(j=0, ans=0; j<n; j++) //求每个旋转置换的循环节,和寻找连通子 图类似。 { if(flag[j]==0) //若j节点未曾访问过,表示一个新的循环, ans++; { ans++; for(k=j; flag[k]==0; k=g[k]) flag[k] = 1; } } res += pow(3*1.0, ans); //算下旋转置换后的结果; for(j=1; (j+j)<n; j++) //每次翻转置换的结果,沿翻转轴对称点交换 位置; {//由于程序里每次旋转置换在翻转置换之前进行,故每次都要用同一个翻 转处理,而不必分情况讨论; k = g[j]; g[j] = g[n-j]; g[n-j] = k; } memset(flag, 0, sizeof(flag)); for(j=0, ans=0; j<n; j++) //求每次翻转置换的循环节数,和求连通子 图类似; { if(flag[j]==0) //若j节点没被访问过,表示一个新的循环, ans++; { ans++; for(k=j; flag[k]==0; k=g[k]) flag[k] = 1; } } res += pow(3*1.0, ans); //累加上翻转置换的结果; } printf("%.0lf/n",res/(2*n)); } return 0; }