poj1286

时间:2023-03-09 08:02:46
poj1286

等价类计数问题,我们就先构造置换群

显然置换分为两种类型,旋转和翻折

先考虑旋转,每旋转i格子,这个置换的循环数为gcd(i,n); (1<=i<=n) 为什么是这个范围,下篇报告再说

翻转也是n种,显然要分奇偶讨论

奇数时,翻转只能从顶点,都是一个类型的,循环数位(n+1)/2

偶数时,翻转既能沿边折,循环数为n/2,又可以沿关于圆心的对称点连线折,循环数为(n-2)/2+2=(n+2)/2

然后直接套一下polya定理就可以了,还是比较简单容易分析出来的

 var d:array[..] of int64;
    i,n:longint;
    ans:int64; function gcd(a,b:longint):longint;
  begin
    if b= then exit(a)
    else exit(gcd(b,a mod b));
  end; begin
  readln(n);
  d[]:=;
  for i:= to do
    d[i]:=d[i-]*;   while n<>- do
  begin
    if n= then writeln()
    else begin
      ans:=;
      for i:= to n do
        ans:=ans+d[gcd(n,i)];
      if n mod = then ans:=ans+n*d[(n+) div ]
      else ans:=ans+n div *d[n div ]+n div *d[(n+) div ];
      writeln(ans div div n);
    end;
    readln(n);
  end;
end.