Split Divisibilities (Project Euler 598)
题目大意:
求将$100!$ 拆成$a*b$的方案数,其中$a<=b$并且它们的约数个数一样多。
思路:
先将$100!$质因数分解, 结果如图:

首先想到一个暴力DP, dp[i][j][k]表示考虑完前i个质数, 目前a有j个约数,b有k个约数的方案数。 用map保存状态。
答案就是sum(dp[25][j][j]).
但是状态数会很多(大概有1e8个状态),所以考虑 中途相遇法。 对前3个质数做一次DP, 然后对后面22个质数做一次DP。
最后答案就是 sum (dp1[3][i1][j1] * dp2[22][i2][j2]) 条件是 i1 * i2 = j1 * j2. 即 i1 / j1 = j2 / i2 .
一个优化是只保存 j和k互质的状态。 然后 最后 答案的时候 枚举 i1,j1, 在 dp2中 查找 j2 / i2 = i1 / j1的点 。
因为a<=b,所以最后答案还需要除以2.
代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <set>
#include <cstring>
#include <map>
#include <queue>
using namespace std; typedef long long ll;
#define N 10000000
#define M 1100
typedef pair<int,int> pii; bool flag[N];
int p[N],phi[N]; struct node
{
ll x,y;
bool operator < (const node &t)const
{
return y*t.x<x*t.y;
}
node (ll _x = , ll _y = ){x = _x; y = _y;}
}; map<node, ll> mp; ll Gcd(ll x, ll y)
{
ll tmp;
while (y)
{
tmp = x % y;
x = y, y = tmp;
}
return x;
} void Get_Primes(int lim)
{
phi[]=;
for (int i=;i<=lim;i++)
{
if (!flag[i]) p[++p[]]=i,phi[i]=i-;
for (int j=;j<=p[] && i*p[j]<=lim;j++)
{
flag[i*p[j]]=true;
if (i%p[j]==)
{
phi[i*p[j]]=phi[i]*p[j];
break;
}
else phi[i*p[j]]=phi[i]*(p[j]-);
}
}
} map<pair<ll,ll>, ll> f[], g[];
int cnt[]; int main()
{
freopen("in.in","r",stdin);
freopen("out.out","w",stdout); int n = ;
Get_Primes(n);
for (int i = ; i <= p[]; ++i)
{
int x = p[i];
while (x <= n) cnt[i] += n / x, x *= p[i];
} f[][make_pair(,)] = ;
for (int i = ; i <= ; ++i)
{
for (map<pair<ll,ll>, ll>::iterator it = f[i - ].begin(); it != f[i - ].end(); it++)
{
ll k1 = (*it).first.first, k2 = (*it).first.second;
for (int j = ; j <= cnt[i]; ++j)
{
ll kx = k1 * (j + ), ky = k2 * (cnt[i] - j + ) , d = Gcd(kx, ky);
f[i][make_pair(kx / d, ky / d)] += (*it).second;
}
}
}
g[][make_pair(,)] = ;
for (int i = ; i <= p[] - ; ++i)
{
for (map<pair<ll,ll>, ll>::iterator it = g[i - ].begin(); it != g[i - ].end(); it++)
{
ll k1 = (*it).first.first, k2 = (*it).first.second;
for (int j = ; j <= cnt[i + ]; ++j)
{
ll kx = k1 * (j + ), ky = k2 * (cnt[i + ] - j + ), d = Gcd(kx, ky);
g[i][make_pair(kx / d, ky / d)] += (*it).second;
}
}
}
for (map<pair<ll,ll>, ll>::iterator it = g[p[] - ].begin(); it != g[p[] - ].end(); it++)
{
ll x = (*it).first.first, y = (*it).first.second;
mp[node(x, y)] += (*it).second;
} ll res = ;
for (map<pair<ll,ll>, ll>::iterator it = f[].begin(); it != f[].end(); it++)
{
ll x = (*it).first.first, y = (*it).first.second;
res += (*it).second * mp[node(y, x)];
}
cout << res / << endl;
return ;
}
答案:543194779059
Split Divisibilities (Project Euler 598)的更多相关文章
- Python练习题 049:Project Euler 022:姓名分值
本题来自 Project Euler 第22题:https://projecteuler.net/problem=22 ''' Project Euler: Problem 22: Names sco ...
- Python练习题 041:Project Euler 013:求和、取前10位数值
本题来自 Project Euler 第13题:https://projecteuler.net/problem=13 # Project Euler: Problem 13: Large sum # ...
- Python练习题 039:Project Euler 011:网格中4个数字的最大乘积
本题来自 Project Euler 第11题:https://projecteuler.net/problem=11 # Project Euler: Problem 10: Largest pro ...
- [project euler] program 4
上一次接触 project euler 还是2011年的事情,做了前三道题,后来被第四题卡住了,前面几题的代码也没有保留下来. 今天试着暴力破解了一下,代码如下: (我大概是第 172,719 个解出 ...
- Python练习题 029:Project Euler 001:3和5的倍数
开始做 Project Euler 的练习题.网站上总共有565题,真是个大题库啊! # Project Euler, Problem 1: Multiples of 3 and 5 # If we ...
- Project Euler 9
题意:三个正整数a + b + c = 1000,a*a + b*b = c*c.求a*b*c. 解法:可以暴力枚举,但是也有数学方法. 首先,a,b,c中肯定有至少一个为偶数,否则和不可能为以上两个 ...
- Project Euler 44: Find the smallest pair of pentagonal numbers whose sum and difference is pentagonal.
In Problem 42 we dealt with triangular problems, in Problem 44 of Project Euler we deal with pentago ...
- project euler 169
project euler 169 题目链接:https://projecteuler.net/problem=169 参考题解:http://tieba.baidu.com/p/2738022069 ...
- 【Project Euler 8】Largest product in a series
题目要求是: The four adjacent digits in the 1000-digit number that have the greatest product are 9 × 9 × ...
随机推荐
- CSS3:固定textarea文本域宽度
textarea在一些浏览器上可以被拖拉改变大小,为了保持美观,可以通过 CSS3 resize 属性禁掉 textarea{resize:none; //不允许用户调整元素大小}
- Intel haxm安装失败问题解决
在安装Intel haxm为安卓模拟器加速时,会遇到提示VT-X未开启问题,问题提示如下图 工具/原料 Intel haxm 安卓模拟器 方法/步骤 确认你的处理器是否是Intel的,如果是A ...
- js各种验证总结
1.邮箱验证 function isEmail(str){ var reg = /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+((\.[a-zA-Z0-9_-]{2,3}){1 ...
- WebLogic Server 12.1.2后的字符型安装模式
weblogic Server 12.1.1全部都可以用原来方式. WebLogic Server 12.1.2后已经取消了console安装模式,目前只有gui和静默安装模式.并且安装方式下也有很大 ...
- 2015年Ubuntu最新Redmine的安装和配置
近期须要在公司内部搭建一个项目管理平台Redmine,在摸索了一天之后.最终配置成功,在这里分享给大家. 公司server的系统是Ubuntu14.04,要安装的是最新的Redmine3.0. 因为R ...
- iOS:XMPP即时聊天知识
XMPP即时聊天框架:XMPPFramework XMPP The Extensible Messaging and Presence Protocol(可扩展通讯和表示协议). 基于XML XM ...
- D3.js系列——动态效果和Update、Enter、Exit的理解
一.动态效果 D3 支持制作动态的图表.有时候,图表的变化需要缓慢的发生,以便于让用户看清楚变化的过程,也能给用户不小的友好感. 1.什么是动态效果 前面制作的图表是一蹴而就地出现,然后绘制完成后不再 ...
- android 博客列表
1. Hongyang http://blog.csdn.net/lmj623565791/article/details/37970961
- SVN回到历史版本--转载
svn回到历史的某个版本 在代码的编写过程中,难免有些错误需要修改,或者想从以前的文件进行代码修改,这样就涉及到版本的追踪,如果你以前提交时日志写的非常清楚,那版本追踪回滚起来就事半功倍.得心应手.下 ...
- 查看tomcat启动文件都干点啥---catalina.bat
在上一次查看tomcat启动文件都干点啥一文中,我们总结出,startup.bat文件的作用就是找到catalina.bat文件,然后把参数传递给它,在startup.bat中,调用catalina. ...