问题描述
- tgopknight正在教sc捉数学题,今天他教的是加法和乘法和乘方。
- 唐沟铺的tgopknight果然神,他是这样教导的:
- “加法是基本的四则运算之一,它是指将两个或者两个以上的数、量合起来,变成一个数、量的计算。
- 乘法是指将相同的数加起来的快捷方式。其运算结果称为积。从哲学角度解析,乘法是加法的量变导致的质变结果。
- 求
n
个相同因数乘积的运算,叫做乘方。
- 好!我们来举个例子比如1+2=3、
1×2=2
、
32=9
- “现在你都学会了么?”
- “蒽!”sc回答道,“这怎么能难倒tgopknight?”
- 骑士大爷得意的笑了一笑,现在你应该就会捉这道题了:
- 已知
a+b+c=n,a2+b2+c2=m,a3+b3+c3=k
,求解
a,b,c
。
- 这可难倒了聪明的sc,她立刻给tgopknight去看,tgopknight虽然是丰之崎学园的学神,但是高端科学家唐沟铺骑士的题岂能简简单单的秒掉。她想到了机智聪明的学OI的你一定可以解决
输入格式
- 四个整数
n,m,k,p
- 其中
n,m,k
如上文所述,
p
为输出格式的参数
输出格式
- 由于a,b,c可能有多组解,且实数具有一定的精度误差。本题采取了特殊的处理方式。
- 选手仅需要输出
ap+bp+cp
可以保证其值唯一确定。输出采取A/B的形式,其中
(A,B)=1
,若答案为
0
请输出0/1
数据范围
- Subtask1:
10
分,测试点数1:
n=6,m=14,k=36,1≤p≤10
- Subtask2:
10
分,测试点数1:
n=1,m=2,k=3,1≤p≤10
- Subtask3:
30
分,测试点数5:
p=4,0≤n,m,k≤10
- Subtask4:
50
分,测试点数10:对于前5个测试点满足:
0≤n,m,k,p≤15
- 对于后五个测试点满足:
0≤n,m,k≤20,0≤p≤10
分析 DP + 数学
代码
#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;
int n, m, k, P;
ll g[15], f[15];
inline ll gcd(ll x, ll y)
{
ll r = x % y;
while (r) x = y, y = r, r = x % y;
return y;
}
int main()
{
freopen("math.in", "r", stdin);
freopen("math.out", "w", stdout);
scanf("%d%d%d%d", &n, &m, &k, &P);
f[1] = n; f[2] = m; f[3] = k; g[1] = g[2] = g[3] = 1;
const ll p = n * n - m,
q = 2 * k + n * n * n - 3 * m * n;
for (int i = 4; i <= P; ++i)
{
ll ax = n * f[i - 1], ay = g[i - 1];
ll bx = p * f[i - 2], by = 2 * g[i - 2];
ll cx = q * f[i - 3], cy = 6 * g[i - 3];
g[i] = ay * by / gcd(ay, by);
g[i] = g[i] * cy / gcd(g[i], cy);
f[i] = ax * g[i] / ay - bx * g[i] / by + cx * g[i] / cy;
ll tmp = gcd(f[i], g[i]);
f[i] /= tmp; g[i] /= tmp;
}
if (g[P] < 0 && f[P] > 0)
g[P] = -g[P], f[P] = -f[P];
cout << f[P] << "/" << g[P] << endl;
fclose(stdin); fclose(stdout);
return 0;
}