VJ传送门


因为有每种颜色个数的限制,所以不能使用Polya

考虑退一步,使用Burnside引理求解

回忆一下Burnside引理,它需要求的是置换群中每一个置换的不动点个数,也就是施加一次置换之后新状态与原状态相同的状态个数。而施加一次置换之后状态不变的充要条件是:对于这个置换中的每一个循环,循环中所有位置的颜色都相同。

为了叙述方便,约定\(f(i,j,k,l) = \frac{i!}{j!k!l!}\)

首先考虑旋转。假设某一种旋转置换使得\(i\)位置的珠子变到\(i+k\)位置\((k \in [1,N] , N = a+b+c)\),不难知道这个置换是由\(gcd(N,k)\)个\(\frac{N}{gcd(N,k)}\)阶循环构成的。

假设\(\frac{N}{gcd(N,k)} | a\ \&\&\ \frac{N}{gcd(N,k)} | b\ \&\&\ \frac{N}{gcd(N,k)} | c\)(如果这个条件不成立显然没有方案),那么这\(gcd(N,k)\)个循环中有\(\frac{a}{\frac{N}{gcd(N,k)}}\)个是全白色,\(\frac{b}{\frac{N}{gcd(N,k)}}\)个是全灰色,\(\frac{c}{\frac{N}{gcd(N,k)}}\)个是全黑色,这是一个本质不同的可重排列计数问题,染色方案有\(f(gcd(N,k) , \frac{a}{\frac{N}{gcd(N,k)}} ,\frac{b}{\frac{N}{gcd(N,k)}}, \frac{c}{\frac{N}{gcd(N,k)}})\)种

接着考虑翻转。这里需要分类讨论一下:

①\(2 \not\mid N\),意味着所有的轴会且只会经过一个珠子。在这种情况下,总共有\(N\)种翻转置换,每一个置换都是由\(1\)个\(1\)阶循环和\(\frac{N-1}{2}\)个\(2\)阶循环组成。枚举这一个\(1\)阶循环的颜色,那么不动点个数为\((f(\frac{N - 1}{2} , \frac{a - 1}{2} , \frac{b}{2} , \frac{c}{2}) + f(\frac{N - 1}{2} , \frac{a}{2} , \frac{b - 1}{2} , \frac{c}{2}) + f(\frac{N - 1}{2} , \frac{a}{2} , \frac{b}{2} , \frac{c - 1}{2}) ) \times N\)

②\(2 | N\),意味着有\(\frac{N}{2}\)个轴不经过珠子,有\(\frac{N}{2}\)个对称轴经过\(2\)个珠子,跟上面一样枚举\(1\)阶循环的颜色计算答案,式子太长不想写了留给读者自行思考

还有这道题似乎要写高精

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<cctype>
#include<algorithm>
#include<cstring>
#include<iomanip>
#include<queue>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<vector>
#include<cmath>
//This code is written by Itst
using namespace std; inline int read(){
int a = 0;
char c = getchar();
bool f = 0;
while(!isdigit(c) && c != EOF){
if(c == '-')
f = 1;
c = getchar();
}
if(c == EOF)
exit(0);
while(isdigit(c)){
a = a * 10 + c - 48;
c = getchar();
}
return f ? -a : a;
} struct Bignum{
int a[107];
int& operator [](int x){return a[x];}
Bignum(int b = 0){
memset(a , 0 , sizeof(a));
a[0] = 0;
while(b){
a[++a[0]] = b % 10;
b /= 10;
}
}
Bignum operator =(int b){
return *this = Bignum(b);
}
void input(){
string s;
cin >> s;
a[0] = s.size();
for(int i = 1 ; i <= a[0] ; ++i)
a[i] = s[s.size() - i] - '0';
}
void output(){
if(!a[0])
putchar('0');
for(int i = a[0] ; i ; --i)
putchar(a[i] + '0');
putchar('\n');
}
Bignum operator +(Bignum b){
Bignum c;
c[0] = max(a[0] , b[0]);
for(int i = 1 ; i <= c[0] ; ++i)
if((c[i] += a[i] + b[i]) >= 10){
c[i] -= 10;
++c[i + 1];
}
if(c[c[0] + 1])
++c[0];
return c;
}
Bignum operator +=(Bignum b){
return *this = *this + b;
}
Bignum operator -(Bignum b){
Bignum c;
c[0] = max(a[0] , b[0]);
for(int i = 1 ; i <= c[0] ; ++i)
if((c[i] += a[i] - b[i]) < 0){
c[i] += 10;
--c[i + 1];
}
while(c[0] && !c[c[0]])
--c[0];
return c;
}
Bignum operator -=(Bignum b){
return *this = *this - b;
}
Bignum operator *(Bignum b){
if(!b[0])
return b;
Bignum c;
c[0] = a[0] + b[0] - 1;
for(int i = 1 ; i <= a[0] ; ++i)
for(int j = 1 ; j <= b[0] ; ++j)
c[i + j - 1] += a[i] * b[j];
for(int i = 1 ; i <= c[0] ; ++i)
if(c[i] >= 10){
c[i + 1] += c[i] / 10;
c[i] %= 10;
if(i == c[0])
++c[0];
}
while(c[0] && !c[c[0]])
--c[0];
return c;
}
Bignum operator *=(Bignum b){
return *this = *this * b;
}
Bignum operator ^(int a){
Bignum times(1) , b(*this);
while(a){
if(a & 1)
times *= b;
b *= b;
a >>= 1;
}
return times;
}
bool operator >(Bignum b)const{
if(a[0] > b[0])
return 1;
if(a[0] < b[0])
return 0;
for(int i = a[0] ; i ; --i)
if(a[i] > b[i])
return 1;
else
if(a[i] < b[i])
return 0;
return 0;
}
bool operator >= (Bignum b){
if(a[0] > b[0])
return 1;
if(a[0] < b[0])
return 0;
for(int i = a[0] ; i ; --i)
if(a[i] > b[i])
return 1;
else
if(a[i] < b[i])
return 0;
return 1;
}
Bignum operator /(Bignum b){
Bignum c , d = *this , e;
c[0] = a[0] - b[0] + 1;
for(int i = c[0] ; i ; --i){
e = b * (Bignum(10) ^ (i - 1));
for(int j = 1 ; j <= 10 ; ++j)
if((e * j) > d){
d -= e * (j - 1);
c[i] = j - 1;
break;
}
}
while(c[0] && !c[c[0]])
--c[0];
return c;
}
Bignum operator /=(Bignum b){
return *this = *this / b;
}
Bignum operator %(Bignum b){
return *this - *this / b * b;
}
Bignum operator %=(Bignum b){
return *this = *this % b;
}
}jc[41];
int a , b , c , N;
Bignum ans; inline int gcd(int a , int b){
int r = a % b;
while(r){
a = b;
b = r;
r = a % b;
}
return b;
} inline Bignum calc(int x , int a , int b , int c){
if(a % x || b % x || c % x || a < 0 || b < 0 || c < 0)
return 0;
int N = a + b + c;
return jc[N / x] / jc[a / x] / jc[b / x] / jc[c / x];
} int main(){
#ifndef ONLINE_JUDGE
//freopen("in","r",stdin);
freopen("out","w",stdout);
#endif
jc[0] = 1;
for(int i = 1 ; i <= 40 ; ++i)
jc[i] = jc[i - 1] * i;
for(int T = read() ; T ; --T){
ans = 0;
a = read();
b = read();
c = read();
N = a + b + c;
for(int i = 1 ; i <= N ; ++i)
ans += calc(N / gcd(i , N) , a , b , c);
if(N & 1)
ans += (calc(2 , a - 1 , b , c) + calc(2 , a , b - 1 , c) + calc(2 , a , b , c - 1)) * N;
else
ans += (calc(2 , a , b , c) + calc(2 , a - 1 , b - 1 , c) + calc(2 , a - 1 , b , c - 1) + calc(2 , a , b - 1 , c - 1)) * N;
ans = ans / (2 * N);
ans.output();
}
return 0;
}

UVA11255 Necklace Burnside、组合的更多相关文章

  1. POJ 1286 Necklace of Beads ——Burnside

    [题目分析] 题目大意:一个环有n个点,共染三种颜色.问 在旋转和对称的情况下有多少种本质不同的方案数. Burnside直接做. [代码] #include <cstdio> #incl ...

  2. Luogu P5564 [Celeste-B]Say Goodbye (多项式、FFT、Burnside引理、组合计数)

    题目链接 https://www.luogu.org/problem/P5564 题解 这题最重要的一步是读明白题. 为了方便起见下面设环长可以是\(1\), 最后统计答案时去掉即可. 实际上就相当于 ...

  3. BZOJ 1488 Luogu P4727 [HNOI2009]图的同构 (Burnside引理、组合计数)

    题目链接 (Luogu) https://www.luogu.org/problem/P4727 (BZOJ) https://www.lydsy.com/JudgeOnline/problem.ph ...

  4. [Luogu4916]魔力环[Burnside引理、组合计数、容斥]

    题意 题目链接 分析 sπo yyb 代码 #include<bits/stdc++.h> using namespace std; typedef long long LL; #defi ...

  5. 【Luogu4916】魔力环(Burnside引理,组合计数)

    考虑\(Burside\)引理,设\(f(x)\)表示置换拆成循环的个数为\(x\)时的答案,那么最终的结果就是\(\displaystyle \frac{\sum_{i=1}^n f(gcd(i,n ...

  6. poj 1286 Necklace of Beads【polya定理+burnside引理】

    和poj 2409差不多,就是k变成3了,详见 还有不一样的地方是记得特判n==0的情况不然会RE #include<iostream> #include<cstdio> us ...

  7. Luogu P4708 画画 (Burnside引理、组合计数)

    题目链接 https://www.luogu.org/problem/P4708 题解 看上去Luogu P4706-4709是Sdchr神仙出的一场比赛,一道水题和三道很有趣的题终于全过了纪念QAQ ...

  8. POJ burnside&&polya整理练习

    POJ 2409 Let it Bead 这题就是polya公式的直接套用,唯一麻烦的是置换群的种类数,由于可以翻转,所以除了要加上pow(c,gcd(s,i))这些平面旋转的置换群,还要加上翻转的. ...

  9. 等价类计数问题(Polya定理和burnside引理)

    零.约定: (置换等名词会在前置知识中有解释) \(1.\)在本文中,题目要求的染色方案等统称为"元素". \(2.\)两个元素严格相等我们记做"\(=\)", ...

随机推荐

  1. [VUE ERROR] Invalid options in vue.config.js: "publicPath" is not allowed

    项目在build的时候报的这个错误: 具体原因是因为版本支持的问题,publicPath 属性到 vue-cli 3.2.0 之后才支持,所以将 publicPaht 改成 baseUrl 即可,或者 ...

  2. off by null 实战

    前言 off by null 是一个比较有意思的技术 下面通过 hctf2018 的 heapstrom_zero 实战一波. 相关文件(exp, 题目)位于 https://gitee.com/ha ...

  3. .NetCore(四) 在Nginx部署

    ​本篇主要体验一下Nginx的使用,之前只接触过IIS. 一.Nginxa) ASP.NET Core内置了Kestrel服务器,但功能简单,主要用于SelfHost,正式运行还是要依赖IIS.Apa ...

  4. 手把手教你撸一个简易的 webpack

    背景 随着前端复杂度的不断提升,诞生出很多打包工具,比如最先的grunt,gulp.到后来的webpack和Parcel.但是目前很多脚手架工具,比如vue-cli已经帮我们集成了一些构建工具的使用. ...

  5. 分享MYSQL中的各种高可用技术

    分享MYSQL中的各种高可用技术 图片和资料来源于姜承尧老师(MYSQL技术内幕作者) mysql高可用各个技术的比较 数据库的可靠指的是数据可靠 数据库可用指的是数据库服务可用 可靠的是数据:例如工 ...

  6. c#事务处理(sqlTransaction)

    事务: /// <summary> /// 删除考勤 /// </summary> /// <param name="dto">Id</p ...

  7. 万能Makefile,前戏做足项目做起来才顺畅。

    # 获取要编译的源码 SRC :=$(wildcard *.cpp) OBJ :=$(patsubst %.cpp,%.o,$(SRC)) # 编译参数 CC :=g++ STD :=-std=c++ ...

  8. windows7下的一个好玩的,你绝对不知道

    今天学到了一个好东西,分享一下, windows7系统测试是可以的,其他系统暂时没测试,分享给大家玩玩: 在桌面新建一个文件夹: 文件夹重命名为:GodMode.{ED7BA470-8E54-465E ...

  9. Reachability

    一.Reachability中介绍了取得/检测网络状态的方法. 二.使用 1.添加源文件:Reachability.h和Reachability.m 2.添加framework———SystemCon ...

  10. 【2017下集美大学软工1412班_助教博客】团队作业7——第二次项目冲刺(Beta阶段)成绩公示

    作业要求 团队作业7 团队评分结果 Beta计划 Total GN SX GJ LC AP WT PHILOSOPHER 3 1 0 1.5 0 0.5 0 三人行 3.5 1 1 1 0 0.5 0 ...