zoukankan      html  css  js  c++  java
  • Transposing is Fun——Polya定理

    题面

      SPOJ419 ( 洛谷 )

    解析

      $SPOJ422$是同一道题,只是$422$需要一些优化,思路是一样的。

      一个点$(i, j)$转置后变为$(j,i)$,其中$0leqslant i < 2^a, 0 leqslant j < 2^b$,可以视作$i*2^b+j$变为了$j*2^a+i$。那么答案就等于$2^{a+b}-$循环节个数。

      现在的问题就变成如何求循环节个数。将$i*2^b+j$视为首位相接的二进制串,$j*2^a+i$是其右移$b$位所得,问题再次转化:一个含有$a+b$个点的环,每个点有$2$种颜色,若一种染色方案向右旋转$b$位与另一方案相同,则将两种方案视为同一种方案,问有多少种不同的染色方案。

      长为$a+b$的环上一个点不断向右移$b$位,回到起点所需要的步数为$frac{lcm(a+b, b)}{b}$,因此该环上有$frac{a+b}{lcm(a+b,b)/b}=gcd(a+b,b)=gcd(a,b)$条不相交循环,令$g=gcd(a,b)$,将相邻$g$位看作一个点,于是问题又一次转化:一个含有$frac{a+b}{g}$个点的环,每个点有$2^g$种颜色,若一种染色方案向右旋转$1$位与另一方案相同,则将两种方案视为同一种方案,问有多少种不同的染色方案。

      这是$polya$计数的经典题了,但之前没有总结过,这里就稍微写一下,令$n=frac{a+b}{g}$,$m=2^g$

      则有:$$egin{align*}Ans&=frac{1}{n}sum_{i=1}^n m^{gcd(i,n)}\&=frac{1}{n}sum_{d|n}m^dsum_{i=1}^n[gcd(i,n)==d]\&=frac{1}{n}sum_{d|n}m^dsum_{i=1}^{frac{n}{d}}[gcd(frac{n}{d},i)==1]\&=frac{1}{n}sum_{d|n}m^dvarphi(frac{n}{d})end{align*}$$

      还有一些实现上的优化,这个就看代码了。

     代码:

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<vector>
    using namespace std;
    typedef long long ll;
    const int maxn = 1000005, mod = 1000003;
    
    int add(int x, int y)
    {
        return x + y < mod? x + y: x + y - mod;
    }
    
    int rdc(int x, int y)
    {
        return x - y < 0? x - y + mod: x - y;
    }
    
    ll qpow(ll x, int y)
    {
        ll ret = 1;
        while(y)
        {
            if(y&1)
                ret = ret * x % mod;
            x = x * x % mod;
            y >>= 1;
        }
        return ret;
    }
    
    int cnt, pri[maxn], phi[maxn<<1], fct[maxn<<1];
    bool notp[maxn<<1];
    
    void Euler()
    {
        phi[1] = 1;
        for(int i = 2; i <= 2000000; ++i)
        {
            if(!notp[i])
            {
                pri[++cnt] = i;
                phi[i] = ((i - 1 < mod)? i - 1: i - 1 - mod);
                fct[i] = i;
            }
            for(int j = 1; j <= cnt; ++j)
            {
                if(i * pri[j] > 2000000)    break;
                notp[i*pri[j]] = 1;
                fct[i*pri[j]] = pri[j];
                if(i % pri[j] == 0)
                {
                    phi[i*pri[j]] = phi[i] * pri[j] % mod;
                    break;
                }
                phi[i*pri[j]] = phi[i] * (pri[j] - 1) % mod;
            }
        }
    }
    
    int T, n, m, g, d, ans;
    int pw2[maxn<<1];
    
    int gcd(int x, int y)
    {
        return (y == 0)? x: gcd(y, x % y);
    }
    
    int a[50], num[50], tot;
    
    void dfs(int x, int idx)
    {
        if(x == tot + 1)
        {
            ans = add(ans, qpow(pw2[g], idx) * phi[d/idx] % mod);
            return ;
        }
        for(int i = 0; i <= num[x]; ++i)
        {
            dfs(x + 1, idx);
            idx *= a[x];
        }
    }
    
    int main()
    {
        Euler();
        pw2[0] = 1;
        for(int i = 1; i <= 2000000; ++i)
            pw2[i] = add(pw2[i-1], pw2[i-1]);
        scanf("%d", &T);
        while(T --)
        {
            scanf("%d%d", &n, &m);
            if(!n || !m)
            {
                printf("0
    ");
                continue;
            }
            g = gcd(n, m);
            d = (n + m) / g;
            ans = 0;
            tot = 0;
            for(int i = d; i != 1; i /= fct[i])
            {
                if(fct[i] == a[tot])
                {
                    ++ num[tot];
                }
                else
                {
                    a[++tot] = fct[i];
                    num[tot] = 1;
                }
            }
            dfs(1, 1);
            printf("%d
    ", rdc(pw2[n+m], ans * qpow(d, mod - 2) % mod));
        }
        return 0;
    }
    View Code 
  • 相关阅读:
    hdu 6188 Duizi and Shunzi
    区间第k大
    AtCoder Regular Contest 081 E
    hdu 6170 Two strings
    hdu 6156 Palindrome Function
    2017百度之星初赛(B)-1006-小小粉丝度度熊 hdu 6119
    AtCoder Regular Contest 080 E
    hdu 6069 Counting Divisors
    hdu 6058 Kanade's sum (多校3)
    苹果曼和树
  • 原文地址:https://www.cnblogs.com/Joker-Yza/p/12676441.html
Copyright © 2011-2022 走看看