Codeforces Round #647 (Div. 2) - Thanks, Algo Muse!
Posted lordxx
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #647 (Div. 2) - Thanks, Algo Muse!相关的知识,希望对你有一定的参考价值。
解决:ABCDE 补题:F
A。
使a2,4,*8或者/2,/4,/8能否得到b。
令a为更小的值,a/2*2的效果一样,又a是小值,故只用考虑a*({2^k})能否得到b即可。然后贪心的选。(3=2+1,2=1+1)
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<bitset>
#include<map>
//#include<regex>
#include<cstdio>
#include <iomanip>
#pragma GCC optimize(2)
#define up(i,a,b) for(int i=a;i<b;i++)
#define dw(i,a,b) for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
ll read()
{
char ch = getchar(); ll x = 0, f = 1;
while (ch<‘0‘ || ch>‘9‘) { if (ch == ‘-‘)f = -1; ch = getchar(); }
while (ch >= ‘0‘ && ch <= ‘9‘) { x = x * 10 + ch - ‘0‘; ch = getchar(); }
return x * f;
}
typedef pair<int, int> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
int t;
ll a, b;
int main()
{
t = read();
while (t--)
{
a = read(), b = read();
if (a > b)swap(a, b);
if (a == b) {
printf("0
");
continue;
}
if (b%a !=0||b&1)
{
printf("-1
");
}
else {
ll temp = b / a;
ll sum = 0;
if (temp & 1)
{
printf("-1
");
continue;
}
bool flag = 0;
dwd(i, 60, 0)
{
if (temp&(1ll << i))
{
if (sum == 0)
sum = i;
else flag = 1;
}
}
if (flag)
{
printf("-1
");
}
else {
int cnt = 0;
while (sum)
{
if (sum >= 3)sum -= 3;
else if (sum >= 2)sum -= 2;
else if (sum >= 1)sum--;
cnt++;
}
printf("%d
", cnt);
}
}
}
return 0;
}
B.
有a^b=c -> a^c=b,b^c=a。故,a[i]^k=a[j],反过来,a[j]^k=a[i],k=a[i]^a[j]所以长度一定为偶数。考虑(n^2)遍历。得到1024以内的所有两两异或值,枚举这些值,当作k使用,判断可行性。
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<bitset>
#include<map>
//#include<regex>
#include<cstdio>
#include <iomanip>
#pragma GCC optimize(2)
#define up(i,a,b) for(int i=a;i<b;i++)
#define dw(i,a,b) for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
ll read()
{
char ch = getchar(); ll x = 0, f = 1;
while (ch<‘0‘ || ch>‘9‘) { if (ch == ‘-‘)f = -1; ch = getchar(); }
while (ch >= ‘0‘ && ch <= ‘9‘) { x = x * 10 + ch - ‘0‘; ch = getchar(); }
return x * f;
}
typedef pair<int, int> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
int t;
int n;
const int N = 2000;
int a[N];
int main()
{
t = read();
while (t--)
{
n = read();
upd(i, 1, n)a[i] = read();
if (n & 1)
{
printf("-1
");
}
else {
vector<int>vec;
sort(a + 1, a + n + 1);
upd(i, 1, n) {
upd(j, i+1, n)
{
int temp = a[i] ^ a[j];
vec.push_back(temp);
} }
sort(vec.begin(), vec.end());
vec.erase(unique(vec.begin(), vec.end()), vec.end());
bool last = 0;
for (auto k : vec)
{
bool flag = 0;
vector<int>temp;
upd(i, 1, n)
{
temp.push_back(a[i] ^ k);
}
sort(temp.begin(), temp.end());
temp.erase(unique(temp.begin(), temp.end()), temp.end());
if (temp.size() != n) {
flag = 1;
}
else {
upd(i, 1, n)
{
if (temp[i - 1] != a[i])
flag = 1;
}
}
if (!flag)
{
printf("%d
", k);
last = 1;
break;
}
}
if (!last) {
printf("-1
");
}
}
}
return 0;
}
C
简单dp预处理。令dp[i]表示,二进制第i为即000..1000..000时,所拥有的不同数量。
(dp[i])=((sum_{j=1}^{i}{dp[j]})+i+1)(例如1000,与0111恰好多了3+1个即i+1)
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<bitset>
#include<map>
//#include<regex>
#include<cstdio>
#include <iomanip>
#pragma GCC optimize(2)
#define up(i,a,b) for(int i=a;i<b;i++)
#define dw(i,a,b) for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
ll read()
{
char ch = getchar(); ll x = 0, f = 1;
while (ch<‘0‘ || ch>‘9‘) { if (ch == ‘-‘)f = -1; ch = getchar(); }
while (ch >= ‘0‘ && ch <= ‘9‘) { x = x * 10 + ch - ‘0‘; ch = getchar(); }
return x * f;
}
typedef pair<int, int> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
ll dp[100];
void init()
{
dp[0] = 1;
dp[1] = 3;
ll sum = 4;
upd(i, 2, 61)
{
dp[i] = sum + i + 1;
sum += dp[i];
}
}
ll t, n;
int main()
{
init();
t = read();
while (t--) {
n = read();
ll ans = 0;
dwd(i, 60, 0) {
if (n&(1ll << i))
{
ans += dp[i];
}
}
printf("%lld
", ans);
}
return 0;
}
D
模拟即可。
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<bitset>
#include<map>
//#include<regex>
#include<cstdio>
#include <iomanip>
#pragma GCC optimize(2)
#define up(i,a,b) for(int i=a;i<b;i++)
#define dw(i,a,b) for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
ll read()
{
char ch = getchar(); ll x = 0, f = 1;
while (ch<‘0‘ || ch>‘9‘) { if (ch == ‘-‘)f = -1; ch = getchar(); }
while (ch >= ‘0‘ && ch <= ‘9‘) { x = x * 10 + ch - ‘0‘; ch = getchar(); }
return x * f;
}
typedef pair<int, int> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
const int N = 5e5 + 10;
int n, m;
vector<int>vec[N];
int a[N];
vector<int>num[N];
int ans[N];
int last[N];
int main() {
n = read();
m = read();
int u, v;
upd(i, 1, m) {
u = read(), v = read();
vec[u].push_back(v);
vec[v].push_back(u);
}
upd(i, 1, n)a[i] = read();
upd(i, 1, n)
{
num[a[i]].push_back(i);
}
int cnt = 0;
bool flag = 0;
upd(i, 1, n)
{
set<int>s;
for (auto k : vec[i])
{
s.insert(a[k]);
}
int mex = 1;
for (auto k : s) {
if (k != mex)
{
break;
}
mex++;
}
if (mex != a[i])flag = 1;
if (flag)break;
}
upd(i, 1, N-5)
{
if (num[i].size())
{
for (auto k : num[i])
{
ans[k] = ++cnt;
}
}
}
if (flag) {
printf("-1
");
}
else {
upd(i, 1, n)last[ans[i]] = i;
upd(i, 1, n)printf("%d ", last[i]);
}
return 0;
}
E
首先给出结论,当我们考虑k进制时。如果从高位考虑到低位。
假设k进制的位数a[1]>=a[2]>=a[3]>=a[4]......
就有(k^{a[1]})>=(k^{a[2]}+k^{a[3]}+...+k^{a[j]})倘若当(k^{a[2]}+k^{a[3]}+...+k^{a[j]}+k^{a[j+1]})>(k^{a[1]}),此时必有(k^{a[2]}+k^{a[3]}+...+k^{a[j]})==(k^{a[1]})
拿二进制举例。枚举最高位假设:100000,最高位=5。接着往后枚举,432
有sum=(2^4+2^3+2^2)二进制表示为011100,倘若再来一个2(100),那么sum+=(2^2)sum二进制表示为100000。可以考虑为因从高位枚举到低位,我们在做树状数组时,有p+=lowbit(p)这里p一定小于最高位2次方的。所以我们这道题目就可以考虑,先往A组扔一个最高位,然后B组去凑这个最高位,当凑齐时,剪掉。然后重复这个操作。
注意的是,这道题目最开始考虑使用1e9+9这个模数。但这道题目卡掉了,猜测应该要使用不常见的模数。
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<bitset>
#include<map>
//#include<regex>
#include<cstdio>
#include <iomanip>
#pragma GCC optimize(2)
#define up(i,a,b) for(int i=a;i<b;i++)
#define dw(i,a,b) for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
ll read()
{
char ch = getchar(); ll x = 0, f = 1;
while (ch<‘0‘ || ch>‘9‘) { if (ch == ‘-‘)f = -1; ch = getchar(); }
while (ch >= ‘0‘ && ch <= ‘9‘) { x = x * 10 + ch - ‘0‘; ch = getchar(); }
return x * f;
}
typedef pair<int, int> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
const int N = 1e6 + 10;
int t;
ll n, p;
int ki[N];
int val[N];
const int mod = 1e9 + 7;
const int modd = 12255871;
ll quick_pow(ll a, ll b,int m)
{
ll res = 1;
while (b)
{
if (b & 1)res = (res*a) % m;
b >>= 1;
a = a * a%m;
}
return res;
}
int main()
{
t = read();
while (t--)
{
n = read(), p = read();
upd(i, 1, n)ki[i] = read();
sort(ki + 1, ki + n + 1);
ll ans1 = 0, ans2 = 0;
dwd(i, n, 1)
{
if (!ans1 && !ans2)
{
ans1 += quick_pow(p, ki[i], mod);
ans2 += quick_pow(p, ki[i], modd);
ans1 %= mod;
ans2 %= modd;
}
else {
ans1 = (ans1 + mod - quick_pow(p, ki[i], mod)) % mod;
ans2 = (ans2 + modd - quick_pow(p, ki[i], modd)) % modd;
}
}
printf("%lld
", ans1%mod);
}
return 0;
}
F
网上看到的一个很有意思的思路。
首先,我们考虑,k的计算。假设x^y=a,那么就有他的权值为(2^k)=lowbit(a)。其中k是权值。故,我们可以考虑,如果k是答案,那么x的lowbit一定等于y的lowbit(且最高位大于等于k),此时才会出现权值至少为k。我们考虑枚举k(因为k很小)。可以发现,当答案为k时,表示lowbit相等的至少最高位是k,故可以x^(1<<k-1)==y^(1<<k-1)来判断条件。
接着,发现因为两个相邻的必须相连,所以我们使用虚点,这个虚点同时连接i<<1,i<<1|1(即相邻的两个点)。但是这样依然没有解决问题。因为这样图连出来,是无序的。我们考虑简化该图。将可以连边的点,所称一个点。即若x和y满足上述条件,缩成一个点。这样构造出来的图,我们可以看成是二分图,一边是x^(1<<k-1)出来的点,一边是虚点。最后保证该项链能做成一个环,且该环中,保证所有点在内,我们只需要跑一个欧拉路即可。
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<bitset>
#include<map>
//#include<regex>
#include<cstdio>
#include <iomanip>
#pragma GCC optimize(2)
#define up(i,a,b) for(int i=a;i<b;i++)
#define dw(i,a,b) for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
ll read()
{
char ch = getchar(); ll x = 0, f = 1;
while (ch<‘0‘ || ch>‘9‘) { if (ch == ‘-‘)f = -1; ch = getchar(); }
while (ch >= ‘0‘ && ch <= ‘9‘) { x = x * 10 + ch - ‘0‘; ch = getchar(); }
return x * f;
}
typedef pair<int, int> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
const int N = 2e6 + 10;
int n;
pir col[N];
vector<pir>vec[N];
int vis[N];
vector<int>ans;
void dfs(int u, int id)
{
while (vec[u].size())
{
pir top = vec[u].back(); vec[u].pop_back();
if (!vis[top.second])
{
vis[top.second] = 1;
dfs(top.first, top.second);
}
}
if (id != -1)ans.push_back(id);
}
bool check(int mask)
{
ans.clear();
int t = mask - 1;
upd(i, 0, n + t)
vec[i].clear();
upd(i, 1, n)
{
vis[(i - 1) << 1] = 0;
vis[(i - 1) << 1 | 1] = 0;
vec[col[i].first&t].push_back(make_pair(t + i, (i - 1) << 1));
vec[t + i].push_back(make_pair(col[i].first&t, (i - 1) << 1));
vec[col[i].second&t].push_back(make_pair(t + i, (i - 1) << 1 | 1));
vec[t + i].push_back(make_pair(col[i].second&t, (i - 1) << 1 | 1));
}
upd(i, 0, t+n)
{
if (vec[i].size() & 1)
{
return 0;
}
}
upd(i, 0, t + n)
{
if (vec[i].size())
{
dfs(i, -1);
break;
}
}
if (ans.size() != 2 * n)
{
return 0;
}
return 1;
}
int main()
{
n = read();
upd(i, 1, n)
{
col[i].first = read(); col[i].second = read();
}
dwd(i, 20, 0)
{
if (check(1 << i))
{
printf("%d
", i);
for (auto k : ans)
{
printf("%d ", k + 1);
}
break;
}
}
return 0;
}
以上是关于Codeforces Round #647 (Div. 2) - Thanks, Algo Muse!的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces Round #647 (Div. 2) - Thanks, Algo Muse!
Codeforces Round #647 (Div. 2) - Thanks, Algo Muse!
Codeforces Round #647 (Div. 2) - Thanks, Algo Muse!
Codeforces Round #647 (Div. 2) B. Johnny and His Hobbies(枚举)
Codeforces Round #647 (Div. 2) B. Johnny and His Hobbies(枚举)
Codeforces Round #647 (Div. 2) D. Johnny and Contribution(BFS)