前言
模板型的题目,需要记录下来。
题目描述
Invoker
On of Vance’s favourite hero is Invoker, Kael. As many people knows Kael can control the elements and combine them to invoke a powerful skill. Vance like Kael very much so he changes the map to make Kael more powerful.
In his new map, Kael can control n kind of elements and he can put m elements equal-spacedly on a magic ring and combine them to invoke a new skill. But if a arrangement can change into another by rotate the magic ring or reverse the ring along the axis, they will invoke the same skill. Now give you n and m how many different skill can Kael invoke? As the number maybe too large, just output the answer mod 1000000007.Input
The first line contains a single positive integer T( T <= 500 ), indicates the number of test cases.
For each test case: give you two positive integers n and m. ( 1 <= n, m <= 10000 )
Output
For each test case: output the case number as shown and then output the answer mod 1000000007 in a line. Look sample for more information.
Sample Input
2
3 4
1 2
Sample Output
Case #1: 21
Case #2: 1
题目大意
我BB酱作为一名资深DOTA玩家,Kale这个英雄对我来说一直都是在黑名单榜首,复杂的技能操作令我头秃(就好像acm一样),这个题的背景就是建立在卡尔搓技能的基础上的,不过呢加入了一个特点——组合没有头尾,也就是说aaab和baaa和abaa和aaba都是一样的,在网上很多教程我觉得写得不错,有一种说法是把它看成一个项链,于是题目变成了这样:
有条n长度的项链,m种不同的颜色,问可以组成多少种不同的项链(翻转与旋转后相同的都算是同一条项链)
解题思路
这道题用到了Polya原理和费马小定理,还有快速幂的知识,对我来说还有些复杂,但是这里还是要把这个题记录一下,因为之前见到过很多这样的题,这次也算是整合一个模板吧。
解题代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
#include <iostream> #include <cstdio> #include <cstring> #include <string> #include <algorithm> #include <climits> #include <cmath> #include <cassert> #define IOS ios_base::sync_with_stdio(0); cin.tie(0); using namespace std; const long long int mod = (long long int)(1e9) + 7; const int MAX = 10005; long long int POW[MAX]; int gcd(int x, int y) { return y == 0 ? x : gcd(y, x % y); } long long int qucik_pow(long long int x, long long int y) { long long int res = 1, tmp = x; while(y) { if(y & 1) res = res * tmp % mod; tmp = tmp * tmp % mod; y >>= 1; } return res; } int main() { int n, t, T, cases = 0; scanf("%d", &T); while(T--) { scanf("%d%d", &t, &n); POW[0] = 1; for(int i = 1; i <= n; ++i) POW[i] = POW[i - 1] * t % mod; long long int a = 0, b = 0; for(int i = 0; i < n; ++i) { a = ( a + POW[gcd(i, n)]) % mod; } if(n % 2) b = n * POW[(n + 1) / 2] % mod; else b = n / 2 * (POW[n / 2 + 1] + POW[n / 2]) % mod; long long int tmp = qucik_pow(2 * n, mod - 2); printf("Case #%d: %lld\n", ++cases, (a + b) * tmp % mod); } return 0; } |
总结
还有很多东西需要学,polya原理需要好好看看,希望能有时间吧。