Mathematics:X-factor Chains(POJ 3421)

题目大意,从1到N,1 = X0, X1, X2, …, Xm = X中间可以分成很多数,另Xi < Xi+1 Xi 可以整除Xi+1 ,求最大长度m和m长度的链有多少条
思路:
很简单,只要把数分解质因数就可以了,最后链条的长度为质因数的个数,组合数为质因数个数的阶乘除以各自重复质因数的阶乘。还记得我发过的GCM和LCM反转的那道题吗,可以用pallord_rho算法分解质因数。
贴代码,第一个是最坑爹的,这一题会专门出数据坑Miller_Rabin算法,所以必须素数验证必须执行8次以上,不能用srand改变种子,否则你就是在和上帝玩骰子。
#include <iostream>
#include <algorithm>
#include <functional>
#include <time.h> using namespace std;
typedef long long LL_INT; bool Miller_Rabin(const LL_INT);
LL_INT witness(const LL_INT,const LL_INT,const LL_INT);
void Find_Factors(const LL_INT, int *const, const int);
LL_INT Pallord_Rho_Theorem(const LL_INT, const int);
LL_INT Multi_Function(LL_INT,const LL_INT);
LL_INT gcd(LL_INT, LL_INT); static LL_INT factors[], factors_num[];
static long long coe[];
static int factors_sum[]; void Inivilize(void)
{
coe[] = ;
for (int i = ; i <= ; i++)
coe[i] = coe[i - ] * i;
} int main(void)
{
LL_INT x;
long long chains_sum;
int prime_sum, len, i; Inivilize();
while (~scanf("%lld", &x))
{
prime_sum = ; len = ;
if (x <= )
printf("0 1\n");
else if (Miller_Rabin(x))//如果是素数,直接返回1 1
printf("1 1\n");
else
{
Find_Factors(x, &prime_sum, );//120是经验值
sort(factors, factors + prime_sum);
factors_num[] = factors[];
memset(factors_sum, , sizeof(factors_sum));
factors_sum[] = ;
for (i = ; i < prime_sum; i++)
{
if (factors[i - ] == factors[i])
factors_sum[len]++;
else
{
factors_num[++len] = factors[i];
factors_sum[len] = ;
}
}
chains_sum = coe[prime_sum];
for (int i = ; i <= len; i++)
chains_sum /= coe[factors_sum[i]];
printf("%d %lld\n", prime_sum, chains_sum);
}
}
return ;
} bool Miller_Rabin(const LL_INT n)
{
if (n == )
return true;//如果是2,就不用判断了
else
{
for (int i = ; i < ; i++)
{
if (!(witness((LL_INT)(rand() % (n - )) + , n - , n) == ))
return false;
}
return true;
}
} LL_INT witness(const LL_INT coe, const LL_INT level, const LL_INT n)
{
LL_INT y, x;
if (level == )
return ;
x = witness(coe, level >> , n); if (x == )
return ;
y = (x*x) % n;
if (y == && x != && x != n - )
return ;//费马小定理的运用
if (level % == )
y = (coe*y) % n; return y;
} void Find_Factors(const LL_INT n, int *const len, const int times)
{
if (n == )
return;
else if (Miller_Rabin(n))
factors[(*len)++] = n;
else
{
LL_INT p = n;
int c = times;
while (p >= n)
p = Pallord_Rho_Theorem(n, c--);
Find_Factors(p, len, times);
Find_Factors(n / p, len, times);
}
} LL_INT Pallord_Rho_Theorem(const LL_INT n, const int c)
{
LL_INT x, y, k = , d;
x = y = rand() % n;//随意取一个随机数 for (int i = ;; i++)
{
x = (Multi_Function(x, n) + c) % n;
d = gcd(n, (y - x + n) % n);//计算|y-x|与n的最大公因数
if ( < d && d < n)
return d;
else if (y == x)
return n;//相当于这个因数分解是失败的,所以直接返回n让外层循环继续
else if (i == k)//brent判据,目的就是找到在偶数周期内找到gcd(x(k)-x(i/2))
{
y = x;//重新y=x,定义循环
k <<= ;
}
}
return n;
} LL_INT Multi_Function(LL_INT x,const LL_INT mod)
{
LL_INT y = x, ans = ;
while (y)//计算y=x^2的取模算法
{
if (y & )
ans = (ans + x) % mod;
x = (x << ) % mod;
y >>= ;
}
return ans;
} LL_INT gcd(LL_INT a, LL_INT b)
{
if (b == )
return a;
return gcd(b, a%b);
}

挺慢的,其实直接用筛法更快,先把表打好,然后再一个一个选就可以了,用筛法的话可以到100ms以内
#include <iostream>
#include <functional>
#include <algorithm> using namespace std; static bool primes[( << ) + ];
static int primes_set[];
static long long fact[]; void Inivilize(int *const primes_sum)
{
int i, j;
primes[] = primes[] = ;
for (i = ; i <= << ; i++)
{
if (!primes[i]) primes_set[(*primes_sum)++] = i;
for (j = ; j*i <= << && j <= i; j++)
{
if (primes[j] == )
primes[j*i] = ;
}
}
fact[] = ;
for (i = ; i <= ; i++)
fact[i] = fact[i - ] * i;
} int main(void)
{
int x, last, i, tmp_div_sum, tmp_last, longest_length, primes_sum = , prime_num;
long long div_sum, chain_sum;
Inivilize(&primes_sum); while (~scanf("%d", &x))
{
if (x == )
printf("0 1\n");
else
{
div_sum = ; last = x; longest_length = ;
for (i = ; last != ; i++)
{
if (!primes[last])
{
longest_length++;
break;
}
prime_num = primes_set[i];
for (tmp_div_sum = , tmp_last = last; tmp_last%prime_num == ;)
{
if (!tmp_last) break;
tmp_last /= prime_num;
tmp_div_sum++; longest_length++;
}
last = tmp_last;
if (tmp_div_sum)
div_sum *= fact[tmp_div_sum];
}
chain_sum = fact[longest_length];
chain_sum /= div_sum;
printf("%d %lld\n", longest_length, chain_sum);
}
}
return ;
}

Mathematics:X-factor Chains(POJ 3421)的更多相关文章
- poj 3421 X-factor Chains——质因数分解
题目:http://poj.org/problem?id=3421 记忆化搜索竟然水过去了.仔细一想时间可能有点不对,但还是水过去了. #include<iostream> #includ ...
- POJ 3421 X-factor Chains
线型素数筛+质因素分解+组合数. AC后发现这样做效率有点低..766ms. #include<stdio.h> #include<string.h> #include< ...
- POJ 3421 X-factor Chains (因式分解+排列组合)
题意:一条整数链,要求相邻两数前一个整除后一个.给出链尾的数,求链的最大长度以及满足最大长度的不同链的数量. 类型:因式分解+排列组合 算法:因式分解的素因子个数即为链长,链中后一个数等于前一个数乘以 ...
- POJ 3421 X-factor Chains | 数论
题意: 给一个x,求最长的排列满足开头是1,结尾是x,前一个数是后一个数的因子 输出长度和这样序列的个数 题解: 把x分解质因数,质因数个数就是答案,接下来考虑怎么求个数 显然这是一个可重集合全排列问 ...
- POJ 3421 X-factor Chains(构造)
这条链依次乘一个因子.因为n<2^20,sqrt(n)分解因子,相同的因子相对顺序取一个. 组合公式计算一下就好. #include<cstdio> #include<iost ...
- POJ 3421分解质因数
X-factor Chains Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 7375 Accepted: 2340 D ...
- POJ 3421
X-factor Chains Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 5111 Accepted: 1622 D ...
- Mathematics:Find a multiple(POJ 2356)
找组合 题目大意:给你N个自然数,请你求出若干个数的组合的和为N的整数倍的数 经典鸽巢原理题目,鸽巢原理的意思是,有N个物品,放在N-1个集合中,则一定存在一个集合有2个元素或以上. 这一题是说有找出 ...
- Mathematics:Raising Modulo Numbers(POJ 1995)
阶乘总和 题目大意:要你算一堆阶乘对m的模... 大水题,对指数二分就可以了... #include <iostream> #include <functional> #inc ...
随机推荐
- 手机注册获取验证码的PHP代码
php代码 <?php require dirname(__FILE__).'/include/common.inc.php';//这是在cms2008下面做的测试 header("c ...
- [译]ES6箭头函数和它的作用域
原文来自我的前端博客: http://www.hacke2.cn/arrow-functions-and-their-scope/ 在ES6很多很棒的新特性中, 箭头函数 (或者大箭头函数)就是其中值 ...
- Linux运维初级教程(一)Shell脚本
序,掌握shell脚本是linux运维工程师的最基础技能. 一.脚本语言 与高级语言不通,脚本语言运行时需要调用相应的解释器来翻译脚本中的内容. 常见的脚本语言有Shell脚本.Python脚本.ph ...
- nyoj 44 子串和 简单动态规划
子串和 时间限制:5000 ms | 内存限制:65535 KB 难度:3 描述 给定一整型数列{a1,a2...,an},找出连续非空子串{ax,ax+1,...,ay},使得该子序列的和最 ...
- Linux中source是什么指令?
命令用法: source FileName 作用:在当前bash环境下读取并执行FileName中的命令. 注:该命令通常用命令“.”来替代. 如:source /etc/profile 与 . / ...
- 8-IO总结
3. 4. 5.
- Javascript高级程序设计——引用类型
对象在javascript中被称为引用类型的值,而且有一些内置的引用类型可以创建特定的对象: 引用类型与传统面向对象中的程序设计的类相似,但实现不同: Object是一个基础类型,其他所有类型都从Ob ...
- Linux 动态监听进程shell
背景 前几天在研究线程的时候,看到一句话说java里的线程Thread.run都会在Linux中fork一个的轻量级进程,于是就想验证一下(笔者的机器是Linux的).当时用top命令的时候,进程总是 ...
- 【转】关于URL编码/javascript/js url 编码/url的三个js编码函数
来源:http://www.cnblogs.com/huzi007/p/4174519.html 关于URL编码/javascript/js url 编码/url的三个js编码函数escape(),e ...
- ProgressDialog使用总结
以前对ProgressDialog不太熟练,特地看到的这个文章 ProgressDialog的使用 ProgressDialog 继承自AlertDialog,AlertDialog继承自Dialo ...