Dancepted

Dancing Acceped!

2018.11.1刷题记录

最近在学新知识,都是例题,比较关键的单独拎出来,其他的就扔代码了。

 

P1072 Hankson 的趣味题 (数论)

题目:

题目描述

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 提高组 第二题
View Code

代码:

#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
*/
View Code

更新:

暴力出奇迹

#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;
}
View Code

 

 

P1463 [POI2002][HAOI2007]反素数 (数论)

题目:

题目描述

对于任何正整数x,其约数的个数记作g(x)。例如g(1)=1、g(6)=4。

如果某个正整数x满足:g(x)>g(i) 0<i<x,则称x为反质数。例如,整数1,24,6等都是反质数。

现在给定一个数N,你能求出不超过N的最大的反质数么?
输入输出格式
输入格式:

一个数N(1<=N<=2,000,000,000)。

输出格式:

不超过N的最大的反质数。

输入输出样例
输入样例#1: 复制

1000

输出样例#1: 复制

840
View Code

代码:

#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;
}
View Code

 

P2261 [CQOI2007]余数求和 (数论)

题目:

题目背景

数学题,无背景
题目描述

给出正整数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
View Code

代码:

#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;
}
View Code

 

CH3101 阶乘分解 (数论)

题目:

描述

给定整数 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
View Code

代码:

#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;
}
View Code

 

posted on 2018-11-02 15:42  Danceped  阅读(242)  评论(0编辑  收藏  举报

导航