ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

10.16 考试解题报告

2019-10-16 15:03:16  阅读:214  来源: 互联网

标签:ch 正整数 int long 解题 freopen 10.16 考试 define


T1

#题目描述 :

对于给定的一个正整数n, 判断n是否能分成若干个正整数之和 (可以重复) ,
其中每个正整数都能表示成两个质数乘积。

#输入描述:

第一行一个正整数 q,表示询问组数。
接下来 q 行,每行一个正整数 n,表示询问。

#输出描述:

q 行,每行一个正整数,为 0 或 1。0 表示不能,1 表示能。

#样例输入:

5
1
4
5
21
25

#样例输出:

0
1
0
1
1

#数据范围:

\(30\%\)的数据满足:\(q\leq20, n\leq20\)
\(60\%\)的数据满足:\(q\leq10000, n\leq5000\)
\(100\%\)的数据满足:\(q\leq10^5, n \leq 10^{18}\)

解题思路:

看到这个奇葩的数据范围,我先看到了\(100\%\)的\(n \leq 10^{18}\)
然后我就不知道怎么想的,写了一个不知道能不能跑过60分的完全背包?

code:

#include <bits/stdc++.h>
#define N 5010
#define ll long long
#define M 1010
#define _ 0

using namespace std;
map<int, int> mp; bool vis[N], b[N];
int q, m, mx, mi = 99999999, cnt, tot;
int po[10000100], f[N], qust[N << 1], prime[N];

int read() {
    int s = 0, f = 0;
    char ch = getchar();
    while (!isdigit(ch)) f |= (ch == '-'), ch = getchar();
    while (isdigit(ch)) s = s * 10 + (ch ^ 48), ch = getchar();
    return f ? -s : s;
}

void erlur(int s) {
    for (int i = 2; i <= s; i++) {
        if (!vis[i]) prime[++cnt] = i;
        for (int j = 1; j <= cnt; j++) {
            if (i * prime[j] > s) break;
            vis[i * prime[j]] = 1;
            if (i % prime[j] == 0) break;
        }
    }
}

int main() {
    freopen("a.in", "r", stdin);
//  freopen("a.out", "w", stdout);
    q = read();
    for (int i = 1; i <= q; i++) {
        qust[i] = read();
        mx = max(mx, qust[i]);
    }
    erlur(mx);
    for (int i = 1; i <= cnt; i++)
        for (int j = 1; j <= cnt; j++) {
            int an = prime[i] * prime[j];
            if (!mp[an] && an <= mx)
                mp[an] = 1, po[++tot] = an, mi = min(mi, an);
        }
    cout << tot << "\n";
    for (int i = 1; i <= q; i++) {
        if (b[qust[i]]) cout << 1 << " ";
        else {
            memset(f, 0, sizeof(f));
            int flag = 0;
            for (int j = 1; j <= tot; j++)
                for (int k = po[j]; k <= qust[i]; k++) {
                    f[k] = max(f[k], f[k - po[j]] + po[j]);
                    if (f[k] == qust[i]) flag = 1;
                }
            if (flag) b[qust[i]] = 1, puts("1");
            else puts("0");
        }
    }
    return 0;
}

在打出来的时候尝试一下\(60\%\)的范围,结果发现自己的程序跑步过去,然后就把前\(1000\)个输了出来,然后发现除了前边的\(1,2,3,5,7,11\)之外所有的数都是1,只有这两个是0.

证明啊

当\(n \leq 20\) 时, 只有\(1,2,3,5,7,11\)无解,其余均有解。
当\(n > 20\) 时, 因为\(n = (n - 4) + 4 = (n-4) + 2 \ast 2\),而\((n-4)\)这个数\(\geq16\), 是一定有解的。
所以,我们证明了对于任意的正整数\(n\),只有\(n = 1,2,3,5,7,11\)时无解,其余均有解。

正解代码:

#include <bits/stdc++.h>
#define N 100010
#define M 1010
#define _ 0

using namespace std;
long long q, n;

int read() {
    int s = 0, f = 0; char ch = getchar();
    while (!isdigit(ch)) f |= (ch == '-'), ch = getchar();
    while (isdigit(ch)) s = s * 10 + (ch ^ 48), ch = getchar();
    return f ? -s : s;
}

int main() {
    freopen("a.in", "r", stdin);
    freopen("a.out", "w", stdout);
    q = read();
    for (int i = 1; i <= q; i++) {
        n = read();
        if (n == 1 || n == 2 || n == 3 || n == 5  || n == 7 || n == 11) puts("0");
        else puts("1");
    }
    return 0;
}

T2

标签:ch,正整数,int,long,解题,freopen,10.16,考试,define
来源: https://www.cnblogs.com/zzz-hhh/p/11685517.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有