A
按题意来即可
#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define pb push_back
#define mst(a, b) memset(a, b, sizeof a)
#define REP(i, x, n) for(int i = x; i < n; ++i)
const int qq = 1e3 + 10;
int gra[qq][qq];
int main(){
int n, k; scanf("%d%d", &n, &k);
for(int i = 1; i <= n; ++i){
for(int j = 1; j <= n; ++j){
if(gra[i][j] == 1) continue;
if(i == j){
if(k >= 1)
gra[i][j] = 1, k--;
}else{
if(k >= 2)
gra[i][j] = gra[j][i] = 1, k -= 2;
}
}
}
if(k){
puts("-1");
return 0;
}
for(int i = 1; i <= n; ++i){
for(int j = 1; j <= n; ++j)
printf("%d ", gra[i][j]);
puts("");
}
return 0;
}B
每个非0距离0的最短距离一定是它左边的第一个0或者它右边的第一个0,计算这两个位置的0即可
#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define pb push_back
#define mst(a, b) memset(a, b, sizeof a)
#define REP(i, x, n) for(int i = x; i < n; ++i)
const int qq = 2e5 + 10;
int num[qq], dist[qq];
int main(){
int n; scanf("%d", &n);
for(int i = 1; i <= n; ++i){
scanf("%d", num + i);
}
int pos = -1;
for(int i = 1; i <= n; ++i){
if(num[i] == 0){
if(pos == -1){
for(int j = i - 1; j >= 1; --j)
dist[j] = i - j;
pos = i;
}else{
for(int j = i - 1; j > pos; --j)
dist[j] = min(dist[j], i - j);
pos = i;
}
continue;
}
if(pos == -1) continue;
dist[i] = i - pos;
}
for(int i = 1; i <= n; ++i)
printf("%d ", dist[i]);
puts("");
return 0;
}
C
题意:给出一个n,一个k,要求在1到n中选k个数,使得和为n,并且这k个数的gcd要最大。
思路:假设选出来的数 a1 + a2 + ... + ak = n, 那么令 g = gcd(a1, a2, ... , ak), 则 b1 + b2 + ... + bk = n/g, 很显然这个g是n的因子,那么我们枚举n的因子判断可行性即可,注意这里n的最大值是1e10, 那么当k大于1e6的时候其实就是不可能的,因为算最小的情况 从1加到1e6是大于1e10的,并且k > n的时候也不可能,排除这两个情况就可以直接做了。
#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define pb push_back
#define pill pair<int, int>
#define mst(a, b) memset(a, b, sizeof a)
#define REP(i, x, n) for(int i = x; i <= n; ++i)
const int qq = 1e5 + 10;
int main(){
LL n, k;
scanf("%lld%lld", &n, &k);
if(k >= 1e6 || k > n){
puts("-1");
return 0;
}
LL f = (1 + k) * k / 2;
LL ans = 0;
for(LL i = 1; i * i <= n; ++i){
if(n % i == 0){
if(i >= f){
ans = n / i;
break;
}else if(n / i >= f){
ans = i;
}
}
}
if(!ans){
puts("-1");
return 0;
}
LL sum = 0;
for(int i = 1; i < k; ++i)
printf("%lld ", i * ans), sum += i * ans;
printf("%lld\n", n - sum);
return 0;
}
E
题意:给出一个n一个k,然后给出一个长度为n的字符串,字符只有四种,L,W,D,?,分别代表输,赢,平,任意,现在要求在最后一个回合的时要求输赢数的绝对值等于k,并且前面任意一个回合结束以后输赢的绝对值不能等于k,现在问你把?填完,求一种符合要求的解。
思路:dp[i][j]代表第i回合,赢 - 输数为j的字符串是否存在,因为有负数,所以可以把整体向右平移一个n,然后就状态转移就好。
#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define pb push_back
#define pill pair<int, int>
#define mst(a, b) memset(a, b, sizeof a)
#define REP(i, x, n) for(int i = x; i <= n; ++i)
const int qq = 2e3 + 10;
int dp[qq][qq], pre[qq][qq];
char st[qq];
int n, k;
int main(){
scanf("%d%d", &n, &k);
scanf("%s", st + 1);
if(k > n){
puts("NO");
return 0;
}
dp[0][n] = 1;
for(int i = 1; i <= n; ++i){
for(int j = 0; j <= n << 1; ++j){
if((j == n - k or j == n + k) and i != n) continue;
if(st[i] == 'W' and j - 1 >= 0 and dp[i - 1][j - 1]) dp[i][j] = 1, pre[i][j] = -1;
if(st[i] == 'D' and dp[i - 1][j]) dp[i][j] = 1, pre[i][j] = 0;
if(st[i] == 'L' and j + 1 <= (n << 1) and dp[i - 1][j + 1]) dp[i][j] = 1, pre[i][j] = 1;
if(st[i] == '?'){
if(dp[i - 1][j - 1] and j - 1 >= 0) dp[i][j] = 1, pre[i][j] = -1;
if(dp[i - 1][j]) dp[i][j] = 1, pre[i][j] = 0;
if(dp[i - 1][j + 1] and j + 1 <= (n << 1)) dp[i][j] = 1, pre[i][j] = 1;
}
}
}
// printf("%d %d\n", dp[n][n + k], dp[n][n - k]);
if(!dp[n][n - k] and !dp[n][n + k]){
puts("NO");
return 0;
}
int a = n, b;
if(dp[n][n + k]) b = n + k;
else b = n - k;
while(a > 0){
if(pre[a][b] == -1) st[a] = 'W';
else if(pre[a][b] == 1) st[a] = 'L';
else st[a] = 'D';
b = b + pre[a][b];
a = a - 1;
}
printf("%s\n", st + 1);
return 0;
}
F
题意:给出n个数,要求求出gcd = 1的子序列的数量
思路:我们可以处理出gcd = i * k (k = 1, 2, 3 ......) 的个数,如果我们要求出gcd = i的数量 就减去gcd等于i的倍数即可得到
#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define pb push_back
#define mst(a, b) memset(a, b, sizeof a)
#define REP(i, x, n) for(int i = x; i < n; ++i)
const int qq = 1e5 + 10;
const int MOD = 1e9 + 7;
LL ans[qq], p[qq];
LL num[qq];
int main(){
int n; scanf("%d", &n);
p[0] = 1;
for(int i = 1; i <= n; ++i)
p[i] = (p[i - 1] * 2LL) % MOD;
int maxn = 0;
for(int i = 1; i <= n; ++i){
int x; scanf("%d", &x);
maxn = max(maxn, x);
num[x]++;
}
for(int i = 1; i<= maxn; ++i){
for(int j = i + i; j <= maxn; j += i) num[i] += num[j];
}
for(int i = maxn; i > 0; --i){
ans[i] = p[num[i]] - 1;
for(int j = i + i; j <= maxn; j += i) ans[i] = (ans[i] - ans[j] + MOD) % MOD;
}
printf("%lld\n", ans[1]);
return 0;
}
本文精选了五道算法竞赛题目并提供了详细的解题思路及代码实现,包括构造图论问题、最短路径优化、数学问题求解、字符串匹配以及组合计数等,适合算法初学者及竞赛选手参考。
661

被折叠的 条评论
为什么被折叠?



