#
Name
Cirno’s Perfect Bitmasks Classroom standard input/output 1 s, 256 MB
Patchouli’s Magical Talisman standard input/output 1 s, 256 MB
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sPY377qf-1656690657896)(https://cdn.codeforces.com/s/76331/images/icons/submit-22x22.png)] [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MXUQ8a22-1656690657897)(https://cdn.codeforces.com/s/76331/images/icons/star_gray_16.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fOBFqXu0-1656690657897)(https://cdn.codeforces.com/s/76331/images/icons/user.png)] x14942
Manipulating History standard input/output 1 s, 256 MB
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-A72piHxG-1656690657897)(https://cdn.codeforces.com/s/76331/images/icons/submit-22x22.png)] [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-i34UN98a-1656690657898)(https://cdn.codeforces.com/s/76331/images/icons/star_gray_16.png)]
The Enchanted Forest standard input/output 2 s, 256 MB
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f6oRME45-1656690657899)(https://cdn.codeforces.com/s/76331/images/icons/submit-22x22.png)] [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NIF8Xz4Q-1656690657899)(https://cdn.codeforces.com/s/76331/images/icons/star_gray_16.png)]
Railway System standard input/output 1 s, 256 MB
Sanae and Giant Robot standard input/output 1 s, 256 MB
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TkM5E1b7-1656690657902)(https://cdn.codeforces.com/s/76331/images/icons/user.png)] x186
对于x,如果x里面含有两个1,那么最小答案就是x的最低一位1所构成的数字。(最低一位and可以是非零,高位与另一个1异或,也是非零)。
如果要是x只有一个1,那么所产生的数字在这一位要有一个1,并且在最低的0位还要有一个1这样,才能保证最后的数字非零。
#include <bits/stdc++.h>
using namespace std;
int main()
{
int T;
cin >> T;
while(T--)
{
int ans;
int x;
cin >> x;
int low1;
int low0;
int cnt1;
low1 = low0 = -1;
cnt1 = 0;
bool fir1 = false;
bool fir0 = false;
for(int i = 0; i <= 31; i++)
{
int t = (x>>i) & 1;
if(!t && !fir0)
{
fir0 = true;
low0 = i;
}
if(t)
{
cnt1 ++;
if(!fir1)
{
low1 = i;
fir1 = true;
}
}
}
if(cnt1 > 1)
{
ans = (1<<low1);
}
else
{
ans = (1 << low1) + (1 << low0);
}
printf("%d\n", ans);
}
return 0;
}
使用的H数组,可以较快地求出最低的1是在哪一位。
H数组的大小稍微大一点没有问题。但是最后必须要mod37.可以处理的范围是0到(1<<35)%37.
在题目中,对于一个偶数,有两种操作:
所以有贪心策略。
对于一个数列,如果存在奇数,那么最终所需要的操作次数就是所有偶数的个数之和(全部和奇数进行合并)
如果要是,没有偶数,那么就寻找把偶数变成奇数的最小操作次数,然后加上所有的偶数的个数。
#include <bits/stdc++.h>
using namespace std;
int H[50];
void process()
{
for(int i = 0; i <= 35; i++)
{
H[((long long)1 << i)%37] = i;
}
}
int main()
{
process();
int T;
cin >> T;
while(T--)
{
int ans;
int num_even = 0;
int minn = INT_MAX;
int buf;
int n;
scanf("%d", &n);
for(int i = 1; i <= n; i++)
{
scanf("%d", &buf);
if(H[(buf & (-buf))%37] != 0)
{
num_even ++;
}
minn = min(minn, H[(buf & (-buf))%37]);
}
if(minn == 0)
ans = num_even;
else
ans = num_even-1+minn;
printf("%d\n", ans);
}
return 0;
}
一定要从题目的描述中跳出来,题目说的很复杂,但是要找一种更加合理的规律。
如果直接按照题目的进行,显然是不可行的。
所以把所有字母全部统计一遍,如果不是偶数,那么就是开始的哪一个字母
#include <bits/stdc++.h>
using namespace std;
#define N 200010
char buf[N];
int cnt[300];
int main()
{
int T;
cin >> T;
while(T--)
{
char ans;
memset(cnt, 0, sizeof(cnt));
int n;
scanf("%d", &n);
for(int i = 1; i <= 2*n+1; i++)
{
scanf("%s", buf+1);
int len = strlen(buf+1);
for(int j = 1; j <= len; j++)
{
int p = buf[j];
cnt[p] = (cnt[p]+1) % 2;
}
}
for(int i = 'a'; i <= 'z'; i++)
{
if(cnt[i]&1 == 1)
{
ans = i;
break;
}
}
printf("%c\n", ans);
}
return 0;
}
这一道题目中有两个贪心的维度
所以分为两种情况:
如果不能走完全图,那么就用尺取法,找到区间蘑菇最多的数目。然后加上第二种情况的最优值。
否则就所有蘑菇加上第二种的最优值。
#include
using namespace std;
#define N 200010
int s[N];
int main()
{
int T;
cin >> T;
while(T--)
{
long long ans = 0;
int n, k;
scanf("%d%d", &n, &k);
for(int i = 1; i <= n; i++)
{
scanf("%d", s+i);
}
if(k >= n)
{
for(int i = 1; i <= n; i++)
{
ans += s[i];
}
ans += (long long)(k-1) * n;
ans -= (long long)n * (n-1) / 2;
}
else
{
long long tmp = 0;
int l = 1;
int r = k;
for(int i = 1; i <= r; i++) tmp += s[i];
ans = tmp;
while(r+1 <= n)
{
tmp-=s[l++];
tmp+=s[++r];
ans = max(tmp, ans);
}
ans += (long long)k*(k-1)/2;
}
printf("%lld\n", ans);
}
return 0;
}
有n个节点,m条边,你可以询问2m次,询问的m串中为1,代表包含这条边,如果为0,就代表不包含这条边。在这种情况下,会得到最大生成树的权值。
然后最后得出最小生成树的权值。
这道题目需要知道最小生成树的克鲁斯卡尔算法。
对于最大生成树,可以进行类推:从把所有的边进行从大到小的排序,然后从最大的边开始,如果加上这一条边不会构成环,那么就选择这一条边。否则不选择这条边。
证明:按照树的定义:数的边数m是图的定点数n的n-1。
假设遇到一条边,满足与已经选择的边不构成回路,但是没有选择,那么在按照这种方法得到最大生成树之后,加上这条边,一定有回路。而这条边与比他大的边不会构成回路,那么只能是与比他小的边构成回路。这样的话,删除比他小的边,又称为了一颗树,但是权值比之前的大。
得证!
所以对于当前的最大的边,一定被选择在最大生成树里面。
如果把这条边删除,有两种情况
对于割边,最小生成树里面一定有它。而对于可以替代的边,最小生成树里面一定没有它。
对于下一次询问,删除这条边即可
对于2m次询问内容:
使用m次询问所有的边的长度
使用1次询问整个图的最大生成树
使用m-1次缩小范围。
最小的一条边一定在最小生成树里面。
#include <bits/stdc++.h>
using namespace std;
priority_queue<pair<int, int> > pq;
int n, m;
int edge[600];
void ask(int k, bool tag)
{
printf("? ");
for(int i = 1; i <= k-1; i++)
{
if(tag) putchar('0');
else putchar('1');
}
if(tag) putchar('1');
else putchar('0');
for(int i = k+1; i <= m; i++)
{
if(tag) putchar('0');
else putchar('1');
}
putchar('\n');
fflush(stdout);
}
void que()
{
printf("? ");
for(int i = 1; i <= m; i++)
{
printf("%d", edge[i]);
}
putchar('\n');
fflush(stdout);
}
int main()
{
int ans = 0;
scanf("%d%d", &n, &m);
for(int i = 1; i <= m; i++)
{
int buf = 0;
ask(i, true);
scanf("%d", &buf);
pq.push(make_pair(buf, i));
}
for(int i = 1; i <= m; i++) edge[i] = 1;
que();
int res;
int last;
scanf("%d", &res);
last = res;
for(int i = 1; i <= m-1; i++)
{
pair<int, int>t;
t = pq.top();
pq.pop();
edge[t.second] = 0;
que();
scanf("%d", &res);
if(last - res < t.first);//并不需要干什么事情
else
{
ans += t.first;
}
last = res;
}
ans += pq.top().first;
printf("! ");
printf("%d", ans);
fflush(stdout);
return 0;
}
手机扫一扫
移动阅读更方便
你可能感兴趣的文章