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. Java JVM监控工具JConsole简介

    Java JVM监控工具JConsole简介 jconsole命令 功能:打开java监视管理控制台 方法: jconsole [选项1] [选项2] …… [选项n] 常用选项: -help     ...

  2. Expo大作战(三十二)--expo sdk api之Noifications

    简要:本系列文章讲会对expo进行全面的介绍,本人从2017年6月份接触expo以来,对expo的研究断断续续,一路走来将近10个月,废话不多说,接下来你看到内容,讲全部来与官网 我猜去全部机翻+个人 ...

  3. centos7安装rabbitmq 总结

    centos7下安装rabbitmq 折腾了三天最后做了以下总结 先查看一电脑名  :示例 #hostname name 查看一下hosts配置文件:如果如下结果,就要修改下 #cat /etc/ho ...

  4. 【HANA系列】SAP HANA XS使用JavaScript数据交互详解

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[HANA系列]SAP HANA XS使用Jav ...

  5. 使用虚拟环境virtualenv/Virtualenvwrapper隔离多个python

    virtualenv 系统中的多个python混用会导致$PYTHONPATH混乱,或者各个工程对于package的版本要求不同等等情况.有一个简单的解决方案就是用virtualenv来隔离多个pyt ...

  6. python 计时累积超过24小时时继续往上累加

    最近在做一个工具,要求在工具上面加上程序运行的时间,所以做了个计时器 在网上找了很多发现都是24小时制的,超过24小时后就会回0 然后自己根据24小时制修改了一个不停累加时间的 若是想超过24小时后以 ...

  7. asp.net mvc项目使用spring.net发布到IIS后,在访问提示错误 Could not load type from string value 'DALMsSql.DBSessionFactory,DALMsSql'.

    asp.net mvc项目使用spring.net发布到IIS后,在访问提示错误 Could not load type from string value 'DALMsSql.DBSessionFa ...

  8. asp在线压缩和解压缩文件(文件夹)

    <%'\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'\\'\\ 1. c:\windows\system32\cmd.e ...

  9. Mysql连接错误:Mysql Host is blocked because of many connection errors

    环境:linux,mysql5.5.31错误:Host is blocked because of many connection errors; unblock with 'mysqladmin f ...

  10. 如何根据name和value选中radio [问题点数:40分,结帖人zzxap

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html>  <he ...