2018.11.1刷题记录
最近在学新知识,都是例题,比较关键的单独拎出来,其他的就扔代码了。
题目:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
题目描述 Hanks 博士是 BT(Bio-Tech,生物技术) 领域的知名专家,他的儿子名叫 Hankson。现在,刚刚放学回家的 Hankson 正在思考一个有趣的问题。 今天在课堂上,老师讲解了如何求两个正整数c1 c_1c1 和 c2c_2c2 的最大公约数和最小公倍数。现在 Hankson 认为自己已经熟练地掌握了这些知识,他开始思考一个“求公约数”和“求公倍数”之类问题的“逆问题”,这个问题是这样的:已知正整数a0,a1,b0,b1 a_0,a_1,b_0,b_1a0,a1,b0,b1,设某未知正整数x xx 满足: 1. xxx 和 a0a_0a0 的最大公约数是 a1a_1a1; 2. xxx 和 b0b_0b0 的最小公倍数是b1 b_1b1。 Hankson 的“逆问题”就是求出满足条件的正整数xxx。但稍加思索之后,他发现这样的xxx 并不唯一,甚至可能不存在。因此他转而开始考虑如何求解满足条件的 xxx 的个数。请你帮助他编程求解这个问题。 输入输出格式 输入格式: 第一行为一个正整数 nnn,表示有 nnn 组输入数据。接下来的n nn 行每行一组输入数据,为四个正整数 a0,a1,b0,b1a_0,a_1,b_0,b_1a0,a1,b0,b1,每两个整数之间用一个空格隔开。输入数据保证 a0a_0a0 能被 a1a_1a1 整除,b1b_1b1 能被b0 b_0 b0整除。 输出格式: 共 nn n行。每组输入数据的输出结果占一行,为一个整数。 对于每组数据:若不存在这样的 xxx,请输出 000; 若存在这样的x xx,请输出满足条件的x xx 的个数; 输入输出样例 输入样例#1: 复制 2 41 1 96 288 95 1 37 1776 输出样例#1: 复制 6 2 说明 【说明】 第一组输入数据,xx x可以是 9,18,36,72,144,2889,18,36,72,144,2889,18,36,72,144,288,共有6 66 个。 第二组输入数据,xxx 可以是48,1776 48,177648,1776,共有 222 个。 【数据范围】 对于 50%的数据,保证有 1≤a0,a1,b0,b1≤100001≤a_0,a_1,b_0,b_1≤100001≤a0,a1,b0,b1≤10000 且n≤100 n≤100n≤100。 对于 100%的数据,保证有 1≤a0,a1,b0,b1≤2,000,000,0001≤a_0,a_1,b_0,b_1≤2,000,000,0001≤a0,a1,b0,b1≤2,000,000,000 且 n≤2000n≤2000n≤2000。 NOIP 2009 提高组 第二题
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <bits/stdc++.h> using namespace std; const int MAX_N = 1e6 + 5; int prime[MAX_N+1]; void getPrime() { memset(prime, 0, sizeof prime); for (int i = 2; i <= MAX_N; i++) { if (!prime[i]) prime[++prime[0]] = i; for (int j = 1; j <= prime[0] && j <= MAX_N/i; j++) { prime[i*j] = 1; if (i%j == 0) break; } } } inline bool work(int p, int&a, int& b, int& c, int& d, long long& ans) { int ma = 0, mb = 0, mc = 0, md = 0; while (a%p == 0) ma++, a /= p; while (b%p == 0) mb++, b /= p; while (c%p == 0) mc++, c /= p; while (d%p == 0) md++, d /= p; if (ma > mc && mb < md && mc == md) return true; else if (ma > mc && mb == md && mc <= md) return true; else if (ma == mc && mb < md && mc <= md) return true; else if (ma == mc && mb == md && mc <= md) { ans *= md-mc+1; return true; } else { ans = 0; return false; } } int main() { getPrime(); int N; cin >> N; while (N--) { int a, b, c, d; scanf("%d%d%d%d", &a, &c, &b, &d); int maxp = d; long long ans = 1; for (int i = 1; i <= prime[0] && prime[i]*prime[i] <= maxp; i++) { if (d%prime[i]) continue; if (!work(prime[i], a, b, c, d, ans)) break; } if (d > 1) work(d, a, b, c, d, ans); cout << ans << endl; } return 0; } /* 1 7 1 7 7 */
更新:
暴力出奇迹
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <bits/stdc++.h> using namespace std; inline int gcd(int a, int b) { return a%b ? gcd(b, a%b) : b; } int divisor[2000]; void getDivisor(int N) { divisor[0] = 0; for (int i = 1; (long long)i*i <= N; i++) { if (N%i == 0) { divisor[++divisor[0]] = i; if (N/i != i) divisor[++divisor[0]] = N/i; } } } int main() { int n; cin >> n; while (n--) { int a0, a1, b0, b1; scanf("%d%d%d%d", &a0, &a1, &b0, &b1); getDivisor(b1); int ans = 0; for (int i = 1; i <= divisor[0]; i++) { int x = divisor[i]; int g1 = gcd(x, a0), g2 = (long long)x*b0/gcd(x, b0); if (g1 == a1 && g2 == b1) ans++; } cout << ans << endl; } return 0; }
P1463 [POI2002][HAOI2007]反素数 (数论)
题目:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
题目描述 对于任何正整数x,其约数的个数记作g(x)。例如g(1)=1、g(6)=4。 如果某个正整数x满足:g(x)>g(i) 0<i<x,则称x为反质数。例如,整数1,2,4,6等都是反质数。 现在给定一个数N,你能求出不超过N的最大的反质数么? 输入输出格式 输入格式: 一个数N(1<=N<=2,000,000,000)。 输出格式: 不超过N的最大的反质数。 输入输出样例 输入样例#1: 复制 1000 输出样例#1: 复制 840
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <bits/stdc++.h> using namespace std; typedef long long ll; #define tomax(a, b) a = a>b?a:b #define tomin(a, b) a = a<b?a:b const int Prime[10] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29}; ll N; ll ans, gans; void dfs(ll sum, int gsum, int precnt, int i) { if (i == 10 || sum * Prime[i] > N) { if (sum < N) { if (gans < gsum) gans = gsum, ans = sum; else if (gans == gsum) tomin(ans, sum); } return; } for (int j = 1; j <= precnt; j++) { sum *= Prime[i]; if (sum > N) break; dfs(sum, gsum*(j+1), j, i+1); } } int main() { cin >> N; dfs(1, 1, 30, 0); cout << ans << endl; cout << ans << ' ' << gans << endl; return 0; }
题目:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
题目背景 数学题,无背景 题目描述 给出正整数n和k,计算G(n, k)=k mod 1 + k mod 2 + k mod 3 + … + k mod n的值,其中k mod i表示k除以i的余数。例如G(10, 5)=5 mod 1 + 5 mod 2 + 5 mod 3 + 5 mod 4 + 5 mod 5 …… + 5 mod 10=0+1+2+1+0+5+5+5+5+5=29 输入输出格式 输入格式: 两个整数n k 输出格式: 答案 输入输出样例 输入样例#1: 复制 10 5 输出样例#1: 复制 29 说明 30%: n,k <= 1000 60%: n,k <= 10^6 100% n,k <= 10^9
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <bits/stdc++.h> using namespace std; typedef long long ll; #define min(a, b) a<b?a:b ll N, k, ans; int main() { cin >> N >> k; ans = N*k; for (int x = 1, gx; x <= N; x = gx+1) { gx = k/x ? min(k/(k/x), N) : N; ans -= (k/x) * (x+gx) * (gx-x+1) / 2; } cout << ans << endl; return 0; }
题目:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
描述 给定整数 N(1≤N≤10^6),试把阶乘 N! 分解质因数,按照算术基本定理的形式输出分解结果中的 p_i 和 c_i 即可。 输入格式 一个整数N。 输出格式 N! 分解质因数后的结果,共若干行,每行一对pi, ci,表示含有pi^ci项。按照pi从小到大的顺序输出。 样例输入 5 样例输出 2 3 3 1 5 1 样例解释 5! = 120 = 2^3 * 3 * 5
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int MAX_N = 1e6 + 5; int prime[MAX_N+1]; void getPrime() { memset(prime, 0, sizeof prime); for (int i = 2; i < MAX_N; i++) { if (!prime[i]) prime[++prime[0]] = i; for (int j = 1; j <= prime[0] && prime[j] <= MAX_N/i; j++) { prime[prime[j]*i] = 1; if (i%prime[j] == 0) break; } } } int main() { getPrime(); int N; cin >> N; ll cnt; for (int i = 1; prime[i] <= N; i++) { cnt = 0; ll tmp = prime[i]; while (tmp <= N) { cnt += N/tmp; tmp *= prime[i]; } cout << prime[i] << ' ' << cnt << endl; } return 0; }