1003
题意: Bi=maxi∤jAj , i≥2 . 给出Ai,求出所有Bi
思路:直接暴力了,存储Ai和i,然后按Ai从小到大排序,然后从求出每个位置不整除i对应的最大数,在1e5的范围内最多会找100次(这个可以去看看反素数表,1e5的范围内一个数因子最多的个数就是100个,好像是这么多,根据鸽笼原理就是这样咯),最后的复杂度就是O(100 * n)
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <utility>
using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define mst(a, b) memset(a, b, sizeof a)
#define REP(i, x, n) for(int i = x; i <= n; ++i)
const int MOD = 1e9 + 7;
const int qq = 1e5 + 10;
const int INF = 1e9 + 10;
struct Node {
int val, id;
bool operator < (const Node &a) {
return val > a.val;
}
}node[qq];
int n;
int main(){
int t; scanf("%d", &t);
while(t--) {
scanf("%d", &n);
for(int i = 0; i < n; ++i) {
scanf("%d", &node[i].val);
node[i].id = i + 1;
}
sort(node, node + n);
for(int i = 2; i <= n; ++i) {
for(int j = 0; j < n; ++j) {
if(node[j].id % i != 0) {
printf("%d", node[j].val);
printf(i == n ? "\n" : " ");
break;
}
}
}
}
return 0;
}
1008
题意:给出一个m,一个串,在其中选择两个不相交的字串使得 disA,B=∑i=0n−1|Ai−Bn−1−i| 小于等于m,问字串最长是多大
思路:想了很久猜想出来这个题的解法,假设两个串A、B,A串对应的位置是a c, B串对应的位置是b d,假设a < b,可以发现在范围a - d中,两个串是关于中间对称的,所以我想到了枚举对称轴,然后使用尺取法来维护串最大的长度
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <utility>
using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define mst(a, b) memset(a, b, sizeof a)
#define REP(i, x, n) for(int i = x; i <= n; ++i)
const int MOD = 1e9 + 7;
const int qq = 2e5 + 10;
const int INF = 1e9 + 10;
char st[5005];
int n, m, res;
int main(){
int t; scanf("%d", &t);
while(t--) {
scanf("%d", &m);
scanf("%s", st + 1);
n = strlen(st + 1);
res = 0;
for(int k = 1; k < n; ++k) {
int a = k, b = k + 1;
int c = k, d = k + 1;
int sum = 0;
while(a != 0 && b != n + 1) {
sum += abs(st[a] - st[b]);
while(sum > m) {
sum -= abs(st[c] - st[d]);
c--, d++;
}
res = max(res, c - a + 1);
--a, ++b;
}
a = k, b = k + 2;
c = k, d = k + 2;
sum = 0;
while(a != 0 && b != n + 1) {
sum += abs(st[a] - st[b]);
while(sum > m) {
sum -= abs(st[c] - st[d]);
c--, d++;
}
res = max(res, c - a + 1);
--a, ++b;
}
}
printf("%d\n", res);
}
return 0;
}
1010
题意:给出n个点,n - 1条边, pi的父结点是i + 1,现在两个人玩游戏Alice先手,Bob后手,最初结点都是没有颜色的, 玩家Alice只可以选择一个没有颜色的点将它涂为白色,玩家Bob可以选择一个没有颜色的点将它涂为黑色,并且与这个点有边的点都会被涂为黑色(无论它之前是白色还是没有颜色), 玩家Bob由于冲了VIP,所以他有k次机会,可以在游戏中任意时刻去消除一条边,给出这个图,问最终谁会赢
思路:其实首先要明白一点这个k在什么情况下会使用,最开始推整个图是一条链的情况,发现只有n = 2时Bob才会赢,之后就画了几颗奇怪的图发现确实是这样,就猜了猜是不是把图都变成多个结点树为2的子图Bob就能赢,然后就试了试直接Dfs进行标记,搜到底的时候判断一些这点和它的父结点是否被标记,首先判断能不能变成多个结点数为2的子图,然后再判断需要消边的次数是不是小于等于k
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <utility>
using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define mst(a, b) memset(a, b, sizeof a)
#define REP(i, x, n) for(int i = x; i <= n; ++i)
const int MOD = 1e9 + 7;
const int qq = 2e5 + 10;
const int INF = 1e9 + 10;
vector<int> G[505];
int n, k;
int cnt;
bool vis[505];
void Init() {
for(int i = 0; i <= n; ++i) {
G[i].clear();
}
mst(vis, false);
}
bool f;
void Dfs(int u, int fa) {
for(int i = 0; i < (int)G[u].size(); ++i) {
int v = G[u][i];
if(v == fa) continue;
Dfs(v, u);
}
if(!vis[u] && u != 1 && !vis[fa]) vis[u] = vis[fa] = true;
}
int main(){
int t; scanf("%d", &t);
while(t--) {
scanf("%d%d", &n, &k);
Init();
for(int i = 2; i <= n; ++i) {
int x; scanf("%d", &x);
G[x].pb(i), G[i].pb(x);
}
f = true, cnt = 0;
Dfs(1, -1);
for(int i = 1; i <= n; ++i) {
if(!vis[i]) f = false;
}
if(f && n / 2 - 1 <= k) {
puts("Bob");
} else {
puts("Alice");
}
}
return 0;
}
1011
trick 有点疯狂阿、
自己写了两发WA掉了,队友一改就tm对了
题意:有三门课程,给出n个班级选择A课程人数,B课程人数,C课程人数,AB课程人数,BC课程人数,AC课程人数以及ABC课程人数,让你求一个所有班级中参加课程的人数最多的是多少,其中某些班级的数据有错误,可以忽略掉这个班级,保证至少有意组数据正确
思路:先判一下,求出答案后反判一下可以看下这组数据
5 5 5 5 5 5 0
这肯定是不对的
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <utility>
using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define mst(a, b) memset(a, b, sizeof a)
#define REP(i, x, n) for(int i = x; i <= n; ++i)
const int MOD = 1e9 + 7;
const int qq = 2e5 + 10;
const int INF = 1e9 + 10;
int num[105][10];
int main(){
int t; scanf("%d", &t);
while(t--) {
int n; scanf("%d", &n);
int maxn = 0;
for(int i = 1; i <= n; ++i) {
for(int j = 1; j <= 7; ++j) {
scanf("%d", &num[i][j]);
}
if(num[i][4] > min(num[i][1], num[i][2])) continue;
if(num[i][5] > min(num[i][2], num[i][3])) continue;
if(num[i][6] > min(num[i][1], num[i][3])) continue;
if(num[i][7] > min(num[i][4], min(num[i][5], num[i][6]))) continue;
int ans = 0;
for(int j = 1; j <= 7; ++j) {
if(j >= 4 && j <= 6) ans = ans - num[i][j];
else ans = ans + num[i][j];
}
if(ans - num[i][1] - num[i][2] + num[i][4] < 0) continue;
if(ans - num[i][2] - num[i][3] + num[i][5] < 0) continue;
if(ans - num[i][1] - num[i][3] + num[i][6] < 0) continue;
if(ans - num[i][4] - num[i][5] - num[i][6] + num[i][7] * 2 < 0) continue;
maxn = max(maxn, ans);
}
printf("%d\n", maxn);
}
return 0;
}