原题地址:https://www.jisuanke.com/contest/1857?view=challenges&tdsourcetag=s_pcqq_aiomsg
PS:AC代码AC自CSUOJ,在计蒜客上有些题可能会有点格式问题

A. Potato Sacks

题意:给出一个背包的大小,然后给出n个物品,问你能否用这k个物品装满背包.
思路:签到题,01背包。


#include <bits/stdc++.h>
#define eps 1e-8
#define INF 0x3f3f3f3f
#define PI acos(-1)
#define lson l,mid,rt<<1
#define rson mid+1,r,(rt<<1)+1
#define CLR(x,y) memset((x),y,sizeof(x))
#define fuck(x) cerr << #x << "=" << x << endl
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int seed = 131;
const int maxn = 1e5 + 5;
const int mod = 1e9 + 7;
int T;
int a[maxn];
int dp[20][200];
int main() {
    scanf("%d", &T);
    while (T--) {
        CLR(dp, 0);
        int id;
        scanf("%d", &id);
        int w;
        scanf("%d", &w);
        for (int i = 1; i <= 10; i++) {
            scanf("%d", &a[i]);
        }
        for (int i = 1; i <= 10; i++) {
            for (int j = a[i]; j <= w; j++) {
                dp[i][j] = max(dp[i-1][j], dp[i - 1][j - a[i]] + a[i]);
            }
        }
        printf("%d ", id);
        if (dp[10][w] == w) printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}



/**********************************************************************
	Problem: 2270
	User: yiqzq
	Language: C++
	Result: AC
	Time:4 ms
	Memory:2428 kb
**********************************************************************/

C .Hedwig’s Ladder

题意:给你一个如题目描述的图,然后给出你可以走的步数,每次你从左上角出发,要求同一个点之只能经过一次,问你有几种走法。
思路:暴力打表题,然后找规律。
我们对当前的图进行建图,然后跑dfs记录数据即可。
最后可以发现,结果类似与一个斐波那契数列,只不过奇数位要再加个1。
2018 ICPC Greater New York Regional Contest部分题解

#include <bits/stdc++.h>
#define eps 1e-8
#define INF 0x3f3f3f3f
#define PI acos(-1)
#define lson l,mid,rt<<1
#define rson mid+1,r,(rt<<1)+1
#define CLR(x,y) memset((x),y,sizeof(x))
#define fuck(x) cerr << #x << "=" << x << endl
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int seed = 131;
const int maxn = 1e5 + 5;
const int mod = 10007;
struct node {
    int v, nxt;
} e[maxn];
int head[maxn], tot;
void add_edge(int u, int v) {
    e[tot].v = v;
    e[tot].nxt = head[u];
    head[u] = tot++;

    e[tot].v = u;
    e[tot].nxt = head[v];
    head[v] = tot++;
}
int ans = 0;
int vis[maxn];
void dfs(int u, int num) {
    if (num == 0) {
        ans++;
        return;
    }
    vis[u] = 1;
    for (int i = head[u]; ~i; i = e[i].nxt) {
        int v = e[i].v;
        if (vis[v]) continue;
        vis[v] = 1;
        dfs(v, num - 1);
        vis[v] = 0;
    }
}
ll fac[maxn];
int main() {
//    int MAX = 40;
//    CLR(head, -1);
//    for (int i = 1; i <= MAX - 1; i++) {
//        add_edge(i, i + 1);
//    }
//    for (int i = MAX + 1; i <= 2 * MAX - 1; i++) {
//        add_edge(i, i + 1);
//    }
//    for (int i = 1; i <= MAX; i++) {
//        add_edge(i, i + MAX);
//    }
//    for (int i = 1; i <= 30; i++) {
//        ans = 0;
//        CLR(vis, 0);
//        dfs(1, i);
//        printf("i=%d %d\n", i, ans);
//    }
    fac[1] = 2;
    fac[2] = 3;
    for (int i = 3; i <= 1004; i++) {
        fac[i] = fac[i - 1] + fac[i - 2];
        if (i % 2) fac[i]++;
        fac[i] %= mod;
    }
    int T;
    scanf("%d", &T);
    while (T--) {
        int id;
        scanf("%d", &id);
        int x;
        scanf("%d", &x);
        printf("%d %lld\n", id, fac[x]);
    }
    return 0;
}



/**********************************************************************
	Problem: 2272
	User: yiqzq
	Language: C++
	Result: AC
	Time:0 ms
	Memory:4368 kb
**********************************************************************/

E.What time is it anyway?

题意:有n个时钟,还有n个时差,现在你需要确定一个具体时间,满足n个时钟每个都对应着一个时差。
思路:模拟题,难点在于对时间加法的写法。
PS :要注意时钟的的进位,且正确时间要用set去存,因为可能存在有多种答案,但是答案都是一样的情况。

#include <bits/stdc++.h>
#define eps 1e-8
#define INF 0x3f3f3f3f
#define PI acos(-1)
#define lson l,mid,rt<<1
#define rson mid+1,r,(rt<<1)+1
#define CLR(x,y) memset((x),y,sizeof(x))
#define fuck(x) cerr << #x << "=" << x << endl
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int seed = 131;
const int maxn = 100;
const int mod = 1e9 + 7;
int T, id, n;

struct node {
    int h, m, flag;//flag判断是一个时差是一个正数还是负数
    node() {
        h = 0, m = 0;
    }
    node(int h, int m): h(h), m(m) {}
    node(int h, int m, int flag): h(h), m(m), flag(flag) {}
    bool operator < (const node &a)const {
        return h < a.h || (h == a.h && m < a.m);
    }
    node operator + (const node &a)const {//+右边是时差
        node exa;
        if (a.flag)exa.h = h + a.h;
        else exa.h = h - a.h;
        if (a.flag)exa.m = m + a.m;
        else exa.m = m - a.m;
        if (exa.m >= 60) {
            exa.m -= 60;
            exa.h++;
        } else if (exa.m < 0) {
            exa.m += 60;
            exa.h--;
        }
        if (exa.h > 12)exa.h -= 12;
        else if (exa.h < 1) exa.h += 12;
        return exa;
    }
    node operator - (const node &a)const {//+右边是时差
        node exa;
        if (a.flag)exa.h = h - a.h;
        else exa.h = h + a.h;
        if (a.flag)exa.m = m - a.m;
        else exa.m = m + a.m;

        if (exa.m >= 60) {
            exa.m -= 60;
            exa.h++;
        } else if (exa.m < 0) {
            exa.m += 60;
            exa.h--;
        }
        if (exa.h > 12)exa.h -= 12;
        else if (exa.h < 1) exa.h += 12;
        return exa;
    }
} tim[maxn], lag[maxn], correct, ans;
map<node, int>mp;
int cnt = 0;
set<node>S;
void init() {//初始化时钟
    mp.clear();
    for (int i = 1; i <= n; i++) {
        mp[tim[i]]++;
    }
}
void check(node correct) {//判断当前时间是否可行解
    for (int i = 2; i <= n; i++) {
        node t = correct - lag[i];
        if (mp[t]) 
            mp[t]--;
        } else return ;
    }
    ans = correct;
    S.insert(correct);
}
int main() {
    scanf("%d", &T);
    while (T--) {
        S.clear();
        CLR(lag, 0);
        CLR(tim, 0);
        scanf("%d%d", &id, &n);

        for (int i = 1; i <= n; i++) {
            scanf("%d:%d", &tim[i].h, &tim[i].m);
        }
        for (int i = 1; i <= n; i++) {
            char a[20];
            char flag;
            scanf("%s", a + 1);
            sscanf(a + 1, "%c%d:%d", &flag, &lag[i].h, &lag[i].m);
            lag[i].h %= 12;
            if (flag == '+') lag[i].flag = 0;//要和题目数据改成反的
            else lag[i].flag = 1;
        }
        cnt = 0;
        for (int i = 1; i <= n; i++) {//枚举n种正确解释
            init();
            correct = tim[i] + lag[1];
            mp[tim[i]]--;
            check(correct);
        }
        printf("%d ", id);
        int cnt = S.size();
        if (cnt == 1) {
            printf("%d:%02d\n", ans.h, ans.m);
        } else if (cnt >= 2) printf("%d\n", cnt);
        else printf("none\n");
    }
    return 0;
}




G.The Erdös-Straus Conjecture

题意:给出一个nn,满足式子 4n=1a+1b+1c\frac{4}{n}=\frac{1}{a}+\frac{1}{b}+\frac{1}{c},求满足条件的a,b,ca,b,c,且a,b,ca,b,c的字典序是要最小的。
思路:
通过暴力打表前几项,我们发现aa的值都是n/4+1n/4+1,所以猜测a的值是n/4+1n/4+1,(PS:但是不解的是aa的范围应该是[n/4+1,n/4+3][n/4+1,n/4+3], 然后假设我们已知了正确的aa,(令xy=4n1a\frac{x}{y}=\frac{4}{n}-\frac{1}{a})那么又因为a,b,ca,b,c是按照字典序排序的,所以显然bb的范围是[yx+1,2yx][\frac{y}{x}+1,\frac{2y}{x}](取两个极端,1b=1c\frac{1}{b}=\frac{1}{c}或者1c=0\frac{1}{c}=0),最后cc的值就由验算得来。

#include<iostream>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#define fuck(x) cout<<#x<<" = "<<x<<endl;
#define ls (t<<1)
#define rs ((t<<1)+1)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 100086;
const int inf = 2.1e9;
const ll Inf = 999999999999999999;
const int mod = 1000000007;
const double eps = 1e-6;
const double pi = acos(-1);

ll cal(ll n, ll b, ll x, ll y) {
    ll y1 = b * y;
    ll x1 = x * b - y;
    if (x1 == 0) {
        return -1;
    }
    if (y1 % x1 == 0) {
        return y1 / x1;
    } else return -1;
}

int main() {
    int T;
    scanf("%d", &T);
    while (T--) {
        int id;
        scanf("%d", &id);
        ll n;
        scanf("%lld", &n);
        int flag = 0;
        for (ll a = n / 4 + 1; a <= n / 4 + 3; a++) {
            ll x = 4 * a - n;
            ll y = a * n;
            for (ll i = y / x + 1 ; i <= 2 * y / x; i++) {
                ll t = cal(n, i, x, y);
                if (t > 0) {
                    printf("%d %lld %lld %lld\n",id, a, i, t);
                    flag = 1;
                    break;
                }
            }
            if (flag) break;
        }
    }
    return 0;
}

H.Subprime Fibonacci Sequence

题意:定义一种新的运算SP(x),SP(x),xx为质数或者11的时候,返回xx,否则返回px\frac{p}{x}(pp是最小的能被xx整除的质数)。然后定义an=SP(an1+an2)a_n=SP(a_{n-1}+a_{n-2})
然后给出一组任意的a0a_0a1a_1,让你输出是否存在循环节,如果存在,输出循环节位置和循环节长度,并输出循环节。
思路:先打出质数表。然后由于n的范围只有1000,所以我们可以暴力算出a数组。然后由于这个a数组的每一个值只与前两个有关,因此只要有两个数字连续重复,那就肯定会出现循环节了。所以我们可以利用map存取两个数字的复合值,对于遍历到的每一个数,查询map中是否出现过这个数字。然后记录长度和起始位置就行了。

#include <bits/stdc++.h>
#define eps 1e-8
#define INF 0x3f3f3f3f
#define PI acos(-1)
#define lson l,mid,rt<<1
#define rson mid+1,r,(rt<<1)+1
#define CLR(x,y) memset((x),y,sizeof(x))
#define fuck(x) cerr << #x << "=" << x << endl
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int seed = 131;
const int maxn = 1e5 + 5;
const int mod = 1e9 + 7;
int noprime[maxn * 10], pcnt, p[maxn * 10]; //p存的是质数
void getprime(int N) {
    pcnt = 0;
    memset(noprime, 0, sizeof(noprime));//0表示是质数
    noprime[0] = noprime[1] = 1;
    for (int i = 2; i < N; ++i) {
        if (!noprime[i]) {
            p[pcnt++] = i;//p是存的所有质数
        }
        for (int j = 0; j < pcnt && i * p[j] < N; ++j) {
            noprime[i * p[j]] = 1;
            if (i % p[j] == 0)break;
        }
    }
}
int SP(int x) {
    if (x == 1 || noprime[x] == 0) return x;
    for (int i = 0; i < pcnt; i++) {
        if (x % p[i] == 0) return x / p[i];
    }
}
int a[maxn];
int T, id, n;
map<int, int>mp;
int main() {
    getprime(maxn);
    scanf("%d", &T);
    while (T--) {
        mp.clear();
        int len = -1, index = -1;
        scanf("%d%d", &id, &n);
        scanf("%d%d", &a[1], &a[2]);
        printf("%d", id);
        for (int i = 3; i <= 3000; i++) {
            a[i] = SP(a[i - 1] + a[i - 2]);
        }

        for (int i = 1; i <= n - 1; i++) {
            int num = a[i] * 1000000 + a[i + 1];
            if (mp[num]) {
                index = i;
                len = i - mp[num];
                break;
            }
            mp[num] = i;
        }
        if (index != -1) {
            printf(" %d %d\n", index, len);
            for (int i = index, j = 1; i <= len + index + 1; i++, j++) {
                printf("%d", a[i]);
                if (j % 20 == 0 || i == len + index + 1) printf("\n");
                else printf(" ");
            }
        } else {
            printf(" %d 0\n%d\n", n, a[n + 1]);
        }
    }
    return 0;
}
/**********************************************************************
	Problem: 2277
	User: yiqzq
	Language: C++
	Result: AC
	Time:140 ms
	Memory:10232 kb
**********************************************************************/


相关文章: