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 ...
随机推荐
- 不挣扎了,开始学习LINQ TO XML,进而来解析网页。
找到了别人遇到和我一样的问题:http://ylad.codeplex.com/discussions/430095(英文) 一位叫做Mister Goodcat的提供了信息: Short answe ...
- 移除wordpress留言中自动链接功能
默认情况下,在 WordPress 博客的留言中含有 URL,会自动变成可点击的,虽然这样的链接是 nofollow 的,但是还是成为 SPAM 利用的对象,所以可以移除这个自动链接功能. 我们可以在 ...
- 教你如何删除tomcat服务器的stdout.log文件
用Tomcat做WEB服务器的人都知道,有个很让人头痛的问题,就是stdout.log日志文件会自动增长,而且增长得很快. 先来看看我的痛处吧,公司有个WEB应用,就是用Tomcat作为服务器的,由于 ...
- 解决IE6不支持position:fixed的bug
/*完整代码 */ /* 除IE6浏览器的通用方法 */ .ie6fixedTL { position: fixed; left:; top:; } .ie6fixedBR { position: f ...
- UIMenuController使用
- (void)bubbleDidLongPress:(UILongPressGestureRecognizer *)gestureRecognizer { if(gestureRecognizer. ...
- 跟着百度学PHP[4]-OOP面对对象编程-2-属性和方法
简单的说 变量就是成员属性函数就是成员方法(方法有三:构造方法[即为__construct].成员方法.析构方法[__destruct]) 成员方法和成员属性都是可以加修饰词.比如封装性的方法或者属性 ...
- Sqli-LABS通关笔录-2
在这个关卡学习到了 1.程序的错误不是学校收费乱来的,单引号的错误和减号的错误要明白 单引号报错. 用第一关的PAYLOAD尝试了下. 来看看源码: 那么我们构造的sql也就变成了 $sql=&quo ...
- 剑指Offer 二维数组中的查找
题目描述 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数. 思路法一: * 矩阵是 ...
- auto与decltype
今天搜狗笔试的一道选择题,原题给忘了,但记得所考的知识点.知识点很基础,但很容易忽视. 具体内容可参考C++ Primer. auto :变量取auto后,其所对应的类型 auto一般会 ...
- Android九点图(Nine-Patch)制作及应用
你可能之前还没有听说过Nine-Patch这个名词,它是一种被特殊处理过PNG图片,能够指定哪些区域可以被拉伸而哪些区域不可以. 现在我将手把手教你如何去制作一张九点PNG图像. ---------- ...