CodeForcesGym 100753F Divisions

Divisions

Time Limit: 2000ms
Memory Limit: 262144KB
This problem will be judged on  CodeForcesGym. Original ID: 100753F
64-bit integer IO format: %I64d      Java class name: (Any)
 
解题:大数质因子分解
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long LL;
 4 const int maxn = 100001;
 5 LL mul(LL a,LL b,LL mod) {
 6     if(!a) return 0;
 7     return ((a&1)*b%mod + (mul(a>>1,b,mod)<<1)%mod)%mod;
 8 }
 9 LL quickPow(LL a,LL d,LL n) {
10     LL ret = 1;
11     while(d) {
12         if(d&1) ret = mul(ret,a,n);
13         d >>= 1;
14         a = mul(a,a,n);
15     }
16     return ret;
17 }
18 bool check(LL a,LL d,LL n) {
19     if(n == a) return true;
20     while(~d&1) d >>= 1;
21     LL t = quickPow(a,d,n);
22     while(d < n-1 && t != 1 && t != n-1) {
23         t = mul(t,t,n);
24         d <<= 1;
25     }
26     return (d&1) || t == n-1;
27 }
28 bool isP(LL n) {
29     if(n == 2) return true;
30     if(n < 2 || 0 == (n&1)) return false;
31     static int p[5] = {2,3,7,61,24251};
32     for(int i = 0; i < 5; ++i)
33         if(!check(p[i],n-1,n)) return false;
34     return true;
35 }
36 LL gcd(LL a,LL b) {
37     if(a < 0) return gcd(-a,b);//特别注意,没这个TLE
38     return b?gcd(b,a%b):a;
39 }
40 LL Pollard_rho(LL n,LL c) {
41     LL i = 1,k = 2,x = rand()%n,y = x;
42     while(true) {
43         x = (mul(x,x,n) + c)%n;
44         LL d = gcd(y - x,n);
45         if(d != 1 && d != n) return d;
46         if(y == x) return n;
47         if(++i == k) {
48             y = x;
49             k <<= 1;
50         }
51     }
52 }
53 LL Fac[maxn],tot;
54 void factorization(LL n) {
55     if(isP(n)) {
56         Fac[tot++] = n;
57         return;
58     }
59     LL p = n;
60     while(p >= n) p = Pollard_rho(p,rand()%(n-1)+1);
61     factorization(p);
62     factorization(n/p);
63 }
64 unordered_map<LL,LL>ump;
65 int main() {
66     LL x;
67     srand(time(0));
68     while(~scanf("%I64d",&x)){
69         tot = 0;
70         if(x == 1) {
71             puts("1");
72             continue;
73         }
74         if(isP(x)){
75             puts("2");
76             continue;
77         }
78         factorization(x);
79         ump.clear();
80         for(int i = 0; i < tot; ++i)
81             ump[Fac[i]]++;
82         unsigned long long  ret = 1;
83         for(auto &it:ump) ret *= (it.second + 1);
84         printf("%I64u\n",ret);
85     }
86     return 0;
87 }
88 /*
89 999999999999999989
90 100000007700000049
91 */
View Code

 

转载于:https://www.cnblogs.com/crackpotisback/p/4856163.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个解决这个问题的C++代码示例: ```cpp #include <iostream> #include <vector> using namespace std; int countTeams(int N, int M) { // 创建一个二维矩阵用于表示每对不兼容的选手 vector<vector<int>> incompatible(N + 1, vector<int>(N + 1, 0)); // 输入每对不兼容的选手 for (int i = 0; i < M; i++) { int A, B; cin >> A >> B; incompatible[A][B] = 1; incompatible[B][A] = 1; } // 创建一个一维动态数组用于存储每个队伍的人数 vector<int> teamSizes(N + 1, 0); // 创建一个函数用于递归地计算划分团队的方法数 function<long long(int)> countDivisions = [&](int remaining) { // 如果没有剩余的选手需要分配,则返回1表示找到一种划分方法 if (remaining == 0) { return 1LL; } long long ans = 0; // 遍历所有的选手 for (int i = 1; i <= N; i++) { // 如果当前选手还没有被分配到队伍中 if (teamSizes[i] == 0) { bool validTeam = true; // 检查当前选手与已分配队伍中的选手是否兼容 for (int j = 1; j <= N; j++) { if (teamSizes[j] > 0 && incompatible[i][j]) { validTeam = false; break; } } // 如果当前选手与已分配队伍中的选手兼容,则将其分配到一个队伍中 if (validTeam) { teamSizes[i] = 1; ans += countDivisions(remaining - 1); teamSizes[i] = 0; } } } return ans; }; // 调用函数计算划分团队的方法数 long long ways = countDivisions(N); return ways; } int main() { int N, M; cin >> N >> M; int ways = countTeams(N, M); cout << ways << endl; return 0; } ``` 这段代码使用回溯法递归地计算满足条件的划分方法数。它首先创建一个二维矩阵来表示每对不兼容的选手,然后使用一个一维数组来记录每个队伍的人数。接下来,它定义了一个递归函数`countDivisions`来计算划分团队的方法数。该函数遍历所有的选手,并检查当前选手是否与已分配队伍中的选手兼容。如果兼容,则将该选手分配到一个队伍中,并继续递归地计算剩余选手的划分方法数。最后,将计算得到的划分方法数输出。 注意:这是一种暴力解法,对于大规模的输入可能会超时。如果需要处理更大的输入,请考虑使用更高效的算法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值