日常訓練 20160601 B君的關係 羊毛 (Wolle) Burnside

題意簡述:給一個 n×m×p×q 的四位空間染 col 種顏色,四個方向上的平移置換和任意一種顏色排列的顏色置換所得方案算本質相同的方案,問本質不同的方案數。1n,m,p,q1000 ,1col16
如果不考慮顏色置換,枚舉四個方向上置換走幾步能走完 a,b,c,d (a | A,b | B,c | C,d | D) ,這樣的置換有 φ(a)×φ(b)×φ(c)×φ(d) 種,一次從一個點走回原點的迴路長度是 l=lcm(a,b,c,d) , 有 A×B×C×Dl 種這樣的迴路,每條迴路裏的每個元素都要相同,那麼一條迴路的着色方案只有 1 種,那麼答案就是 φ(a)×φ(b)×φ(c)×φ(d)×cA×B×C×DlA×B×C×D
考慮一種排列的顏色置換,這種置換有用的不是置換本身,而是這個置換中的每個輪換的長度,考慮顏色置換中每一種輪換的長度,如果輪換長度len 是迴路長度l 的因數,那麼就會對迴路貢獻出len 種色盲認不出的方案(顏色置換下的穩定核)。那麼答案就是 φ(a)×φ(b)×φ(c)×φ(d)×(calc(l))A×B×C×DlA×B×C×D
本題是要考慮所有排列的顏色置換,那麼先將 16 自然數拆分,有 231 種拆分,對一種拆分顏色置換其實本質相同,最後只要乘一個係數即可。一種拆分一個輪換內部元素可以隨便換,相同大小的輪換之間也可以隨便換,乘的係數就不難推出了。
最後除以置換方案種類數即可,別忘記除以顏色置換的方案種類數。

#include<bits/stdc++.h>
#define pow HA
typedef long long ll;
const int P = 1e9 + 7;
int A, B, C, D, col, cnt, temp[20], sp[250][20], phi[1001], a[100], b[100], c[100], d[100];
ll fac[20], kind[250], l, ans;
void dfs(int dep, int n, int last) {
    if (n == 0) {
        cnt++;
        for (int i=1; i < dep; i++)
            sp[cnt][temp[i]]++;
        return;
    }
    for (int i=n; i >= last; i--)
        temp[dep] = i,
        dfs(dep + 1, n - i, i);
}
ll gcd(ll a, ll b) {if (b == 0) return a; return gcd(b, a % b); }
ll lcm(ll a, ll b) {return a * b / gcd(a, b); }
ll pow(ll x, ll k) {
    ll ans = 1;
    for (; k; k >>= 1, x = x * x % P)
        if (k & 1ll) ans = ans * x % P;
    return ans;
}
ll calc(ll x, int i) {
    ll ans = 0;
    for (int j=1; j <= col; j++)
        if (x % j == 0)
            ans += sp[i][j] * j;
    return ans;
}
void find(int n, int a[]) {
    for (int i=1; i * i <= n; i++)
        if (n % i == 0)
            a[++a[0]] = i,
            a[++a[0]] = n / i;
    if (a[0] > 1 && a[a[0] - 1] == a[a[0]]) a[0]--;
}
void solve() {
    fac[0] = 1;
    for (int i=1; i <= col; i++)
        fac[i] = fac[i - 1] * i % P;
    for (int i=1; i <= 1000; i++) {
        int t = phi[i] = i;
        for (int j=2; j * j <= t; j++)
            if (t % j == 0) {
                phi[i] = phi[i] / j * (j - 1);
                while (t % j == 0) t /= j;
            }
        if (t > 1) phi[i] = phi[i] / t * (t - 1);
    }
    find(A, a); find(B, b); find(C, c); find(D, d);
    for (int i=1; i <= cnt; i++) {
        ll tans = 0;
        for (int ai=1; ai <= a[0]; ai++)
            for (int bi=1; bi <= b[0]; bi++)
                for (int ci=1; ci <= c[0]; ci++)
                    for (int di=1; di <= d[0]; di++)
                        l = lcm(lcm(a[ai], b[bi]), lcm(c[ci], d[di])),
                        tans = (tans + (ll)phi[a[ai]] * phi[b[bi]] % P * phi[c[ci]] % P * phi[d[di]] % P 
                                * pow(calc(l, i), (ll)A * B * C * D / l)) % P;
        for (int j=1; j <= col; j++)
            tans = tans * pow(pow(j, sp[i][j]) * fac[sp[i][j]] % P, P - 2) % P;
        ans = (ans + tans * fac[col]) % P;
    }
    ans = ans * pow((ll)fac[col] * A % P * B % P * C % P * D % P, P - 2) % P;
    printf("%lld\n",ans);
}
int main() {
    scanf("%d%d%d%d%d",&A,&B,&C,&D,&col);
    dfs(1, col, 1);
    solve();
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章