POJ 1091 跳蚤
2015-09-17 21:23
393 查看
简单分析题意,是要满足a1 * x1 + a2 * x2 + a3 * x3 + ...... am * xm = 1, 就是要求x1, x2, x3 , .....xm的公约数为1, 否则不可能满足。能够组成的数的组合总数为m ^ n种, 然后求有公约数不只有1的数的组合,相减即为结果。
将m分解为质因数的乘积,例如20 = 2 ^ 2 * 5;然后公约数有2的数组个数为(m / 2) ^ n, 总数利用容斥原理求解。
将m分解为质因数的乘积,例如20 = 2 ^ 2 * 5;然后公约数有2的数组个数为(m / 2) ^ n, 总数利用容斥原理求解。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <vector> using namespace std; typedef long long ll; const int LEN = 1e4 + 10; bool is[LEN]; ll prime[LEN]; int cnt; vector <int> v; ll qpow(int n, int m) { ll tmp = n; ll ret = 1; while (m) { if (m & 1) { ret *= tmp; } m >>= 1; tmp = tmp * tmp; } return ret; } void getPrime() { cnt = 0; memset(is, 0, sizeof(is)); for (int i = 2; i < LEN; i++) { if (is[i]) continue; prime[cnt++] = i; for (int j = i * i; j < LEN; j += i) { is[j] = 1; } } } void divide(int n) { v.clear(); for (int i = 0; i < cnt && prime[i] <= n; i++) { if (n % prime[i] == 0) { v.push_back(prime[i]); } while (n % prime[i] == 0) n /= prime[i]; } if (n > 1) v.push_back(n); } ll getNum(int n, int m) { ll g = 0; int tsize = v.size(); int Maxs = (1 << tsize); for (int s = 1; s < Maxs; s++) { ll total = 0, pro = 1; for (int i = 0; i < tsize; i++) { if (s & (1 << i)) { pro *= v[i]; total++; } } if (total & 1) g += qpow(m / pro, n); else g -= qpow(m / pro, n); } return g; } int main() { getPrime(); int n, m; while (~scanf("%d%d", &n, &m)) { divide(m); ll g = getNum(n, m); ll ans = qpow(m, n) - g; printf("%lld\n", ans); } return 0; }
相关文章推荐
- IOS 使代码在ARC和MRC环境编译通用
- Java垃圾回收机制
- 初入android之LinearLayout嵌套线性布局
- I/O流的分类
- httpclient处理跳转(301、302)
- 黑马程序员——面向对象
- WCF入门(12)
- 美团面试失败总结
- 单例集根接口Collection及其常见的两个子接口分析
- iOS经典讲解之iOS8新特性UIAlertController
- Java异常处理总结Exception\Error
- 软件安装时的路径问题
- 利用深搜和宽搜两种算法解决TreeView控件加载文件的问题。
- setAttibute和getParameter的区别
- Segue
- bzoj1650:跳石子
- UVA-12113 Overlapping Squares (回溯+暴力)
- 三阶魔方中心块调整配方和记忆方法
- 利用深搜和宽搜两种算法解决TreeView控件加载文件的问题。
- 面试中常问的关于链表的题目