題意:有三種顏色和n個珠子,讓你求圓形的珠鏈經過旋轉和翻轉或本質不一樣的總數。
分析:這個和poj2409幾乎是一樣的,只是本只有三種顏色,解法是一樣的。。。要是不理解就看看本站的poj2409!!
解法一:
#include<iostream><br />#include<cmath><br />using namespace std;<br />double ans;<br />int n;<br />int gcd(int a, int b)<br />{<br />if(b == 0)<br />return a;<br />return gcd(b, a%b);<br />}<br />int main()<br />{<br />int i,j,k;<br />while(scanf("%d",&n) && n!=-1)<br />{<br />if(n==0)<br />{<br />printf("0/n");<br />continue;<br />}<br />ans = 0.0;<br />for(i=0; i<n; i++)<br />ans += pow(3.0,gcd(n,i));//只有3種顏色、和poj2409幾乎一樣的。、<br />if(n & 1)<br />{<br />for(i=0; i<n; i++)<br />ans += pow(3*1.0, (n+1)/2);<br />}<br />else<br />{<br />for(i=0; i<n/2; i++)<br />{<br />ans += pow(3*1.0, (n+2)/2);<br />ans += pow(3*1.0, n/2);<br />}<br />}<br />printf("%.0lf/n",ans/(2*n));<br />}<br />return 0;<br />}
解法二:很補素的求法,但是最好還是用第一種解法,出現高精度好處理點。
#include<iostream><br />#include<cmath><br />using namespace std;<br />#define M 25<br />int g[M], flag[M];<br />int p,ans,n;<br />double res = 0.0;<br />int main()<br />{<br />int i,j,k;<br />while(scanf("%d",&n))<br />{<br />if(n==-1)<br />break;<br />if(n==0)<br />{<br />printf("0/n");<br />continue;<br />}<br />res = 0.0;<br />memset(g,0,sizeof(g));<br />for(i=0; i<n; i++)//這個迴圈包含了N次旋轉置換和N次翻轉置換<br />{<br />memset(flag,0,sizeof(flag));<br />for(j=0; j<n; j++) //每次旋轉置換後的結果,,<br />g[j] = (i+j) % n;<br />//ans = 0;<br />for(j=0, ans=0; j<n; j++) //求每個旋轉置換的迴圈節,和尋找連通子<br />圖類似。<br />{<br />if(flag[j]==0) //若j節點未曾訪問過,表示一個新的迴圈,<br />ans++;<br />{<br />ans++;<br />for(k=j; flag[k]==0; k=g[k])<br />flag[k] = 1;<br />}<br />}<br />res += pow(3*1.0, ans); //算下旋轉置換後的結果;</p><p>for(j=1; (j+j)<n; j++) //每次翻轉置換的結果,沿翻轉軸對稱點交換<br />位置;<br />{//由於程式裡每次旋轉置換在翻轉置換之前進行,故每次都要用同一個翻<br />轉處理,而不必分情況討論;<br />k = g[j];<br />g[j] = g[n-j];<br />g[n-j] = k;<br />}<br />memset(flag, 0, sizeof(flag));</p><p>for(j=0, ans=0; j<n; j++) //求每次翻轉置換的迴圈節數,和求連通子<br />圖類似;<br />{<br />if(flag[j]==0)//若j節點沒被訪問過,表示一個新的迴圈,<br />ans++;<br />{<br />ans++;<br />for(k=j; flag[k]==0; k=g[k])<br />flag[k] = 1;<br />}<br />}<br />res += pow(3*1.0, ans); //累加上翻轉置換的結果;<br />}<br />printf("%.0lf/n",res/(2*n));<br />}<br />return 0;<br />}<br />