URAL 1091 Tmutarakan Exams (DP或容斥)
来源:互联网 发布:淘宝卖家怎么处理差评 编辑:程序博客网 时间:2024/06/05 09:56
题意
给出一个K和S,求从小于S的数里取出一个K元组的gcd大于1的K元组的数量。
思路
可以dp做,dp的话是经典的计数问题,而且因为数据比较小写起来也比较简单,dp[i][j][k]表示枚举到i时取了j个数此时的gcd为k的个数,则dp[i+1][j+1][gcd(k,i+1)]+=dp[i][j][k],dp[i+1][j][k]+=dp[i][j][k]。
或者容斥,因为所有合数都能用素数来表示,所以我们先枚举所有素数,然后对各个相同的或者不同的素数和进行容斥,总之就是枚举出来所有素数的组合然后奇数加偶数减就可以了。
DP代码
#include <stdio.h>#include <string.h>#include <iostream>#include <algorithm>#include <vector>#include <queue>#include <stack>#include <set>#include <map>#include <string>#include <math.h>#include <stdlib.h>#include <time.h>using namespace std;#define LL long long#define Lowbit(x) ((x)&(-x))#define lson l, mid, rt << 1#define rson mid + 1, r, rt << 1|1#define MP(a, b) make_pair(a, b)const int INF = 0x3f3f3f3f;const int maxn = 1e5 + 7;const double eps = 1e-8;const double PI = acos(-1.0);LL dp[55][55][55];int main(){ //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); int K, S; while (scanf("%d%d", &K, &S) != EOF) { memset(dp, 0, sizeof(dp)); for (int i = 0; i <= S; i++) dp[i][1][i] = 1; for (int i = 1; i < S; i++) for (int j = 1; j <= K; j++) for (int k = 1; k <= S; k++) { dp[i+1][j][k] += dp[i][j][k]; dp[i+1][j+1][__gcd(k, i+1)] += dp[i][j][k]; } int ans = 0; for (int i = 2; i <= S && ans <= 10000; i++) ans += dp[S][K][i]; if (ans > 10000) ans = 10000; printf("%d\n", ans); } return 0;}
容斥代码
#include <stdio.h>#include <string.h>#include <iostream>#include <algorithm>#include <vector>#include <queue>#include <stack>#include <set>#include <map>#include <string>#include <math.h>#include <stdlib.h>#include <time.h>using namespace std;#define LL long long#define Lowbit(x) ((x)&(-x))#define lson l, mid, rt << 1#define rson mid + 1, r, rt << 1|1#define MP(a, b) make_pair(a, b)const int INF = 0x3f3f3f3f;const int maxn = 1e5 + 7;const double eps = 1e-8;const double PI = acos(-1.0);vector<int> prime;vector<int> cnt; //某个素数的可取倍数的数量int vis[55];void init(){ memset(vis, 0, sizeof(vis)); for (int i = 2; i <= 50; i++) { if (!vis[i]) prime.push_back(i); for (int j = i + i; j <= 50; j += i) vis[j] = 1; }}LL C(int n, int m){ if (m > n - m) m = n - m; LL res = 1; for (int i = 0; i < m; i++) { res *= n - i; res /= i + 1; } return res;}LL ans;int K, S;void dfs(int cur, int cnt, int now){ if (now * K > S) return ; if (cur >= prime.size()) { if (!cnt) return ; if (cnt & 1) ans += C(S / now, K); else ans -= C(S / now, K); return ; } dfs(cur + 1, cnt + 1, now * prime[cur]); dfs(cur + 1, cnt, now);}int main(){ //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); init(); while (scanf("%d%d", &K, &S) != EOF) { ans = 0; dfs(0, 0, 1); printf("%lld\n", min(ans, 10000LL)); } return 0;}
0 0
- URAL 1091 Tmutarakan Exams (DP或容斥)
- Ural 1091 Tmutarakan Exams [容斥原理]
- Ural 1091 Tmutarakan Exams【容斥原理】
- URAL 1091 Tmutarakan Exams(容斥原理)
- Ural 1091 Tmutarakan Exams 解题报告(容斥原理)
- 【URAL】1091 Tmutarakan Exams (简单容斥原理)
- URAL 1091 Tmutarakan Exams 【容斥】【组合数】
- ural 1091. Tmutarakan Exams(容斥)
- URAL 1091. Tmutarakan Exams 容斥
- Ural 1091. Tmutarakan Exams 容斥原理
- URAL 1091 Tmutarakan Exams
- Ural 1091. Tmutarakan Exams 排列组合+容斥原理+质因数分解
- Ural 1091 Tmutarakan Exams (水题 容斥+ 莫比乌斯反演)
- URAL 1091. Tmutarakan Exams
- (组合数学3.3.2.1)URAL 1091. Tmutarakan Exams(容斥定理)
- Tmutarakan Exams 简单的容斥定理
- URAL1091 Tmutarakan Exams (容斥原理)
- URAL1091---Tmutarakan Exams(dp)
- JAVA中引用本身占用内存空间的问题
- HDU5120 (容斥原理)
- N
- android 上下滑动重影
- 【leetcode】102. Binary Tree Level Order Traversal
- URAL 1091 Tmutarakan Exams (DP或容斥)
- O
- 使用getIdentifier()获取资源Id
- hdu 3466 Proud Merchants 01背包
- 手柄连接断开时, 后台运行的activity被重新加载
- 【Git+Source Tree使用教程之三】Git Workflow
- 自定义topbar
- 移动时代很多玩法都变了
- LeetCode 226. Invert Binary Tree