【题目链接】
Problem A group
我们发现,如果存在三个人互相不认识的情况,则输出“no”,否则输出“yes”
【代码】
#include<bits/stdc++.h> using namespace std; #define MAXN 110 int i,j,k,n,u; bool g[MAXN][MAXN]; bool flag; template <typename T> inline void read(T &x) { int f = 1; x = 0; char c = getchar(); for (; !isdigit(c); c = getchar()) { if (c == '-') f = -f; } for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0'; x *= f; } template <typename T> inline void write(T x) { if (x < 0) { putchar('-'); x = -x; } if (x > 9) write(x/10); putchar(x%10+'0'); } template <typename T> inline void writeln(T x) { write(x); puts(""); } int main() { while (scanf("%d",&n) != EOF) { flag = false; memset(g,false,sizeof(g)); for (i = 1; i <= n; i++) { while (scanf("%d",&u) && u) g[i][u] = true; } for (i = 1; i <= n; i++) { for (j = 1; j <= n; j++) { for (k = 1; k <= n; k++) { if (i == j || i == k || k == j) continue; if ((!g[i][j] || !g[j][i]) && (!g[i][k] || !g[k][i]) && (!g[k][j] || !g[j][k])) flag = true; } } } if (flag) printf("NO "); else printf("YES "); } return 0; }
Problem B flyer
Part A : 部分分算法
1.1 对于30%的数据,Max(Ci)≤10000,N≤1000,那么,暴力模拟即可
1.2 20%数据满足Ai=Ci,那么,只需用stl库里的map统计答案,即可
1.3 综合前两种部分分算法,期望得分 : 50
1.4 根据异或运算的性质,我们知道两个相同的数异或会抵消,那么我们只需每次枚举那些位置获得了物品,将这些位置
异或,最后,如果异或后的值为0,则无解,否则有解,统计获得了多少物品我们依然用stl库里的map计算,期望得分 :70
Part B : 满分算法:
利用题目中的条件,最多只有一个人获得奇数个物品,那么如果在区间[1,2^32]每个人获得物品的累加和为奇数,则有 解,否则无解
那么,我们考虑 : 对于区间[l,r],我们将它分成[l,mid]和[mid+1,r],如果区间[l,r]每个人获得物品累加和为奇数,则说明
答案在这个区间,否则,答案在区间[mid+1,r]中,那么,我们就可以通过这种二分的方式,求出要求的位置,时间复杂度 :
O(Nlog(N))
【代码】
#include<bits/stdc++.h> using namespace std; #define MAXN 20010 int i,n; long long mx,l,r,mid; long long a[MAXN],b[MAXN],c[MAXN]; inline long long calc(long long l,long long r) { int i; long long k,ans = 0,L,R; for (i = 1; i <= n; i++) { if (a[i] > r || c[i] < l) continue; if (l >= a[i]) { if ((l - a[i]) % b[i] == 0) k = (l - a[i]) / b[i]; else k = (l - a[i]) / b[i] + 1; } else k = 0; L = a[i] + k * b[i]; R = min(r,c[i]); if (L > R) continue; ans += (R - L) / b[i] + 1; } return ans; } int main() { mx = 1; for (i = 1; i <= 32; i++) mx *= 2; while (scanf("%d",&n) != EOF) { for (i = 1; i <= n; i++) scanf("%lld%lld%lld",&a[i],&c[i],&b[i]); if (calc(1,mx) % 2 == 0) printf("DC Qiang is unhappy. "); else { l = 1; r = mx; while (l <= r) { mid = (l + r) >> 1; if (calc(l,mid) % 2 == 1) r = mid - 1; else l = mid + 1; } printf("%lld %lld ",l,calc(l,l)); } } return 0; }
Problem C Weight
Part A : 部分分算法
1.1 对于每次询问DFS,期望得分 : 30
1.2 先处理所有可以称出的物品的重量,将它放入一张哈希表中,每次询问只需查询哈希表中有没有这个数,时间复杂度
大约是O(3^n),期望得分 : 70
Part B : 满分算法
算法1.2起到了引导思考的作用,我们发现如果按1.2做,时间复杂度最劣时达到O(3^24)
考虑使用折半搜索(中途相遇法),将每次询问的数 a 分成 x + y,x在前半部分中,y在后半部分中,那么,我们只需
先求出前半和后半部分能称出物品的重量,每次询问,在前一半数中找到x,如果后一半数中有a - x这个数,输出yes,否则
输出no,显然可以二分,时间复杂度 : O(3^(N/2)+Mlog(3^(N/2)))
【代码】
#include<bits/stdc++.h> using namespace std; #define MAXN 25 int i,j,n,m,len; long long w,t; long long a[MAXN]; vector<long long> x,y; bool flag; template <typename T> inline void read(T &x) { int f = 1; x = 0; char c = getchar(); for (; !isdigit(c); c = getchar()) { if (c == '-') f = -f; } for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0'; x *= f; } template <typename T> inline void write(T x) { if (x < 0) { putchar('-'); x = -x; } if (x > 9) write(x/10); putchar(x%10+'0'); } template <typename T> inline void writeln(T x) { write(x); puts(""); } inline bool search(long long x) { int l = 0,r = y.size() - 1,mid; while (l <= r) { mid = (l + r) >> 1; if (y[mid] == x) return true; if (x < y[mid]) r = mid - 1; else l = mid + 1; } return false; } int main() { read(n); read(m); for (i = 1; i <= n; i++) read(a[i]); x.push_back(0); for (i = 1; i <= n / 2; i++) { len = x.size(); for (j = 0; j < len; j++) { x.push_back(x[j]+a[i]); x.push_back(x[j]-a[i]); } } y.push_back(0); for (i = n / 2 + 1; i <= n; i++) { len = y.size(); for (j = 0; j < len; j++) { y.push_back(y[j]+a[i]); y.push_back(y[j]-a[i]); } } sort(x.begin(),x.end()); unique(x.begin(),x.end()); sort(y.begin(),y.end()); unique(y.begin(),y.end()); for (i = 1; i <= m; i++) { flag = false; read(w); for (j = 0; j < x.size(); j++) { t = w - x[j]; if (search(t)) { flag = true; break; } } if (flag) printf("YES "); else printf("NO "); } return 0; }