原题地址: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。
#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
题意:给出一个,满足式子 ,求满足条件的,且的字典序是要最小的。
思路:
通过暴力打表前几项,我们发现的值都是,所以猜测a的值是,(PS:但是不解的是的范围应该是, 然后假设我们已知了正确的,(令)那么又因为是按照字典序排序的,所以显然的范围是(取两个极端,或者),最后的值就由验算得来。
#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
题意:定义一种新的运算当为质数或者的时候,返回,否则返回(是最小的能被整除的质数)。然后定义。
然后给出一组任意的和,让你输出是否存在循环节,如果存在,输出循环节位置和循环节长度,并输出循环节。
思路:先打出质数表。然后由于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
**********************************************************************/