当前位置: 代码迷 >> 综合 >> OpenJudge C16D Extracurricular Sports(构造/大数)
  详细解决方案

OpenJudge C16D Extracurricular Sports(构造/大数)

热度:3   发布时间:2023-12-08 10:49:39.0

题目链接:
OpenJudge C16D Extracurricular Sports
题意:
构造n个互不相同的数使得这n个数的最小公倍数等于它们之和。2<= n <= 200.如果不存在这样的构造输出-1.
分析:
可以证明2个数的时候不存在这样的构造。当n = 3 时,可以构造出1,2,3。当n = 4时,可以构造出1,4,5,10.
当n>4时,假设前n - 2个数的和是t(最小公倍数也是t),因为n = 3时的合法构造1,2,3,可以令第n - 1个数是2 × t,第n 个数是3×t,这时这n个数的最小公倍数和数字之和都是6*t,因此由n =3 和n =4 的情况,依次往下递推就可以得到答案了。
因为数字比较大,用数组存数字,简单的大数乘法。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <iostream>
#include <climits>
#include <iomanip>
#include <string>
using namespace std;
const int MAX_N = 210;
const int MAX_M = 1010;int ans[MAX_N][MAX_M], sum[MAX_M], tmp[MAX_N], len;void solve(int n)
{memset(ans, 0, sizeof(ans));int st ;if(n & 1){ans[1][0] = 1, ans[2][0] = 2; ans[3][0] = 3;len = 1, sum[0] = 6;st = 5;}else {ans[1][0] = 1, ans[2][0] = 4;ans[3][0] = 5, ans[4][0] = 10;len = 2; sum[0] = 0, sum[1] = 2;st = 6;}for(int i = st; i <= n; i += 2){int carry1 = 0, carry2 = 0, carry3 = 0;int tmp1 = 0, tmp2 = 0, tmp3 = 0;for(int j = 0; j < len; j++){ans[i - 1][j] = sum[j] * 2 + carry1;carry1 = ans[i - 1][j] / 10;ans[i - 1][j] %= 10;ans[i][j] = sum[j] * 3 + carry2;carry2 = ans[i][j] / 10;ans[i][j] %= 10;tmp[j] = sum[j] * 6 + carry3;carry3 = tmp[j] / 10;tmp[j] %= 10;}if(carry1) ans[i - 1][len] = carry1;if(carry2) ans[i][len] = carry2;if(carry3){ tmp[len] = carry3;len++;}for(int j = 0; j < len; j++){sum[j] = tmp[j];}   }   
}int main()
{ios_base::sync_with_stdio(0);cin.tie(0);int T, n;cin >> T;while(T-- > 0){cin >> n;if(n == 2){cout << -1 << endl;continue;}solve(n);for(int i = 1; i <= n; i++){int ed = MAX_M - 10;while(ans[i][ed] == 0) ed--; for(int j = ed; j >= 0; j--){cout << ans[i][j] ;}cout << endl;}//cout << "******" << len << "******" << endl;}return 0;
}