A.EhAb AnD gCd
原题链接:
https://codeforces.com/contest/1325/problem/A
题意:
给出一个x,求得两个数a,b,使得gcd(a,b)+lcm(a,b)==x;
gcd:最大公约数,lcm最大公倍数
题解:
1和任何正整数得gcd是1,lcm是该正整数。
所以直接输出1和x-1即可。
AC代码:
#include <bits/stdc++.h>
//#pragma GCC optimize(2)
//author wjl
using namespace std;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t;
cin>>t;
while(t--)
{
LL x;
cin>>x;
cout<<1<<" "<<x-1<<"\n";
}
return 0;
}
B.CopyCopyCopyCopyCopy
原题链接:
https://codeforces.com/contest/1325/problem/B
题意:
给定一个数组,这个数组可以被连续复制无限次,这里的复制是指将一个原数组的copy添加至原数组的末尾。问最长上升子序列的长度。
题解:
因为可以复制无穷次,所以在每一个复制的数组中,选取当前最小的元素来构成最长上升子序列即可。所以只需要知道原数组有多少个不重复元素即可。
AC代码:
#include <bits/stdc++.h>
//#pragma GCC optimize(2)
//author wjl
using namespace std;
#define LL long long
set<int > s;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t;
cin>>t;
while(t--)
{
int n;
cin>>n;
for(int i=0;i<n;i++)
{
int x;
cin>>x;
s.insert(x);
}
cout<<s.size()<<"\n";
s.clear();
}
return 0;
}
C.Ehab and Path-etic MEXs
原题链接:
https://codeforces.com/contest/1325/problem/C
题意:
通过输入构造一棵n个节点的树,现在要求给每条边编号从0-n-2,且每条边的编号各不相同。定义MEX(u,v)为u节点到v节点的最短路径中所经历边中未出现的最小的自然数。问如何编号,使得对于所有的MEX(u,v)中的最大值最小。
题解:
构造题,对于一个度大于等于三的节点,将与该节点连接的三个边编号0,1,2,其余所有边随意赋值3至n-2即可。
如果没有一个度大于等于三的节点,可以想的出这是一条单链,直接随机从0至n-3即可。
原因:
在所有的最短路径中一定会包含经过0边和1边的最短路径(起始边结束边)。所以max({MEX(u,v)})无论怎么构造一定大于等于2.
没有任何一个最短路径会同时经过一个节点的三条边。所以保证了所有的MEX(u,v)最大值为2.
对于单链来说,无论怎么编号,一定有一个最短路径是从单链一侧到另一侧即包含所有的边,所以无论怎么编号,max({MEX(u,v)})都是n-1。
AC代码:
#include <bits/stdc++.h>
//#pragma GCC optimize(2)
//author wjl
using namespace std;
#define LL long long
const int maxn=1e6+5;
int n;
vector<pair<int,int> > edge[maxn];
int ans[maxn];//记录每条边的编号
bool vis[maxn];//标记每条边是否被编号
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n;
for(int i=1;i<n;i++)
{
int u,v;
cin>>u>>v;
edge[u].push_back(make_pair(v,i));
edge[v].push_back(make_pair(u,i));
}
int a=0;
for(int i=1;i<=n;i++)
{
if(edge[i].size()<=2)continue;
for(int j=0;j<3;j++)
{
ans[edge[i][j].second]=j;
vis[edge[i][j].second]=1;
}
a=3;
break;
}
for(int i=1;i<n;i++)
if(!vis[i])ans[i]=a++;
for(int i=1;i<n;i++)
cout<<ans[i]<<"\n";
return 0;
}
D.Ehab the Xorcist
原题链接:
https://codeforces.com/contest/1325/problem/D
题意:
给两个长整型u,v,求出一个数组,使得数组所有的元素异或和等于u,和等于v,并且数组长度最小。
题解:
一个数组的异或和一定小于一个数组的和。所以u<=v。
现在来构造数组,因为数组和等于v,所以相当于把v拆分开来。
如果u==v,那么数组元素为u即可。
如果u<v,那么长度为1的数组截然不可能 。
设dt=v-u:
- 如果dt为偶数,很容易得到u^(dt/2)^(dt/2)=u,u+dt/2+dt/2=v;这么就构造出了长度为三的数组,当u与dt/2的二进制中每一位都不相同的话,可以将一个dt/2加到u上,即(u|(dt/2))。这样就构造出了长度为2的数组{(u|(dt/2)),dt/2}。
- 如果dt为奇数也就是dt/2无法整除,那么则无法构造出满足题意得数组,输出-1.
AC代码:
#include <bits/stdc++.h>
//#pragma GCC optimize(2)
//author wjl
using namespace std;
#define LL long long
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
LL u,v,k=2;
cin>>u>>v;
LL dt=v-u;
if (u==v && u==0)
{
cout<<0;
return 0;
}
if (dt<0 || (dt&1))
{
cout<<-1;
return 0;
}
if (dt==0)
{
cout<<1<<"\n"<<u;
return 0;
}
dt>>=1;
for (int i=0; i<=61; i++)
{
if ((u&(1ll<<i)) && (dt&(1ll<<i)))
{
k=3;
break;
}
}
if (k==2)
{
cout<<2<<"\n"<<(u|dt)<<" "<<dt;
}
else
{
cout<<3<<"\n"<<u<<" "<<dt<<" "<<dt<<"\n";
}
return 0;
}
欢迎评论!