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 × ...
随机推荐
- What's New In DevTools (Chrome 59)来看看最新Chrome 59的开发者工具又有哪些新功能
原文:https://developers.google.com/web/updates/2017/04/devtools-release-notes#command-menu 参考:https:// ...
- 如何解决nagios安装及运行在的常见错误?(转)
一.安装nrpe的时候,提示:checking for SSL headers… configure: error: Cannot find ssl headers 解决方法如下: yum -y in ...
- RDD编程 上(Spark自学三)
弹性分布式数据集(简称RDD)是Spark对数据的核心抽象.RDD其实就是分布式的元素集合.在Spark中,对数据的操作不外乎创建RDD.转化已有RDD以及调用RDD操作进行求值.而在这一切背后,Sp ...
- gensim加载word2vec训练结果(bin文件)并进行相似度实验
# -*- coding: utf-8 -*- import gensim # 导入模型 model = gensim.models.KeyedVectors.load_word2vec_format ...
- Linux命令--mysqld_safe和mysqld区别
Linux命令--mysqld_safe和mysqld区别 学习了:https://blog.csdn.net/Aaroun/article/details/78143832 mysqld_safe ...
- wine 魔兽争霸
连接参见http://linux-wiki.cn/wiki/%E7%94%A8Wine%E8%BF%90%E8%A1%8C%E9%AD%94%E5%85%BD%E4%BA%89%E9%9C%B8III ...
- HDU - 3038 How Many Answers Are Wrong (带权并查集)
题意:n个数,m次询问,每次问区间a到b之间的和为s,问有几次冲突 思路:带权并查集的应用.[a, b]和为s,所以a-1与b就能够确定一次关系.通过计算与根的距离能够推断出询问的正确性 #inclu ...
- Asp.Net WebApi服务端解决跨域方案
1.特性方式 主要是继承ActionFilterAttribute,重写OnActionExecuted方法,在action执行后,给响应头加上一个键值对. using System.Web.Http ...
- php文件加载路径
<?php require('reusable.php'); echo "相对路径加载<br/>"; /* ./ 表示当前文件所在的目录 ../ 表示当前文件所在 ...
- ExCEL操作技巧集锦,持续更新
1.格式刷 word里面格式化的快捷键很好用,但是excel里面的快捷键用不了,经百度得知: excel双击格式化按钮,可以开启连续应用格式刷模式,单击之后关闭,这样比快捷键好用多了,如下图