BZOJ_1004 Cards

1.题目相关

  • 标签Polya
  • 题目地址:http://www.lydsy.com/JudgeOnline/problem.php?id=1004
  • 题目大意:中文题。

2.思路

  • 比较基础的Polya计数。
  • 利用Burnside引理+K背包+乘法逆元。居然不经意间就会了K背包
  • 前面两个网上书上资料很多,重点讲乘法逆元
  • 先讲一下扩展欧几里得


a·X1 + b·Y1 = gcd(a, b) b·X2 + (a % b)·Y2 = gcd(b, a % b)
其中
gcd(a, b) = gcd(b, a % b) a % b = a-(a/b)·b
整理可得
a·X1 + b·Y1 = b·X2 + (a-(a/b)·b)·Y2
a·X1 + b·Y1 = a·Y2 + b·[X2-(a/b)]·Y2
所以
X1 = Y2 , Y1 = X2-(a/b)·Y2

  • 代码如下
void exgcd(int a, int b, int &x, int &y) {
    if (b == 0) {x = 1; y = 0; return;}
    exgcd(b, a%b, x, y);
    int t = x; x = y; y = t-a/b*y;
}
  • 有了以上的知识就可以来讨论有关 (a/b) % p 的值的问题了
  • 先来看定义:
  • 满足 a·k ≡ 1 (mod p) 的 k 值就是 a 关于 p 的乘法逆元。
  • 为什么要用乘法逆元呢?
  • 当我们要求 (a/b) % p 的值,且 a 很大,无法直接求得 a/b 的值时,我们就要用到乘法逆元。
  • 我们可以通过求 b 关于 p 的乘法逆元 k,将 a 乘上 k 再模 p,即 (a·k) % p。其结果与 (a/b) mod p 等价。
  • 证明如下

根据
b·k ≡ 1 (mod p)
可得
b·k = p·x + 1
k = (p·x + 1) / b
把 k 代入
(a·k) mod p
得原式
= (a·(p·x + 1) / b) % p
= ((a·p·x)/b + a/b) % p
= [((a·p·x)/b) % p + (a/b)] mod p
所以原式等于
(a/b) % p

  • 而 k 的值只要调用一下 exgcd 就好了。但需注意接出来 k 可能是负数,所以要不断加 p 。
  • 代码如下
exgcd(b, p, k, y);
while (k <= 0) k += p;
  • 注意题目中有一个比较坑爹的一个地方:没有(1,2,3...n-1,n)这个置换。其实还是我太菜

点击查看代码

你可能感兴趣的:(BZOJ_1004 Cards)