A. EhAb AnD gCd
题意:给定一个x,求两个正整数a,b,满足a、b的最大公因子和最小公倍数之和等于x
题解:a=1,b=x-1,即可满足
B. CopyCopyCopyCopyCopy
题意:给定一个长度为n的串a,可以得到一个由n个a相连组成的新串,求新串中最长的递增子序列
题解:最长的递增序列,表明同种元素只能出现一次,且a中元素的种类必定小于等于n。
将a排序后,按顺序从新串的第i个(i:1~n)a中取出a[i]。即a的元素种类即为新串的最长递增子序列
#include<bits/stdc++.h>
#define ll long long int
#define _DEBUG
#define vi vector<int>
#define vl vector<ll>
#define vvi vector<vi>
#define pii pair<int,int>
#define pll pair<ll,ll>
#define pil pair<int,ll>
#define pli pair<ll,int>
#define pb push_back
#define mp make_pair
#define fore(index_i,index_l,index_r) for(int index_i=int(index_l);index_i<int(index_r);index_i++)
#define forn(i,n) fore(i,0,n)
#define sz(a) (int)(a).size()
#define all(a) (a).begin(),(a).end()
#define mem(a,i) memset(a,i,sizeof(a))
#define fout(a,n) forn(index_fi,n)cout<<a[index_fi]<<' ';cout<<endl;
#define ffout(a,n,m) forn(index_ffi,n){forn(index_ffj,m)cout<<a[index_ffi][index_ffj]<<' ';cout<<endl;}cout<<endl;
#define out(i) cout<<i<<endl;
#define Pi acos(-1.0)
using namespace std;
const int MOD=int(1e9)+7;
const ll MOD64=(ll)(1e18)+7;
const int INF=0x7fffffff;
const ll INF64=0x7fffffffffffffff;
void file()
{
#ifdef _DEBUG
freopen("cin.txt","r",stdin);
#endif
}
const int N = 1e5+10;
int a[N];
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t;
cin>>t;
while(t--)
{
int n;
cin>>n;
forn(i,n)cin>>a[i];
sort(a,a+n);
int ans=unique(a,a+n)-a;
cout<<ans<<endl;
}
return 0;
}
C. Ehab and Path-etic MEXs
题意:给定一个由n个点组成的树,现给树上每条边赋值,值的取值范围为0~n-2,每条边的值不相同。
求所有点对的最大MEX值最小。
MEX(u,v):在树中,u到v的简单路径上的所有边值中,不被包含的最大自然数。
eg: 边值为0,1,2,那么MEX(u,v)=3
边值为1,2,那么MEX(u,v)=0
#include<bits/stdc++.h>
#define ll long long int
#define _DEBUG
#define vi vector<int>
#define vl vector<ll>
#define vvi vector<vi>
#define pii pair<int,int>
#define pll pair<ll,ll>
#define pil pair<int,ll>
#define pli pair<ll,int>
#define pb push_back
#define mp make_pair
#define fore(index_i,index_l,index_r) for(int index_i=int(index_l);index_i<int(index_r);index_i++)
#define forn(i,n) fore(i,0,n)
#define sz(a) (int)(a).size()
#define all(a) (a).begin(),(a).end()
#define mem(a,i) memset(a,i,sizeof(a))
#define fout(a,n) forn(index_fi,n)cout<<a[index_fi]<<' ';cout<<endl;
#define ffout(a,n,m) forn(index_ffi,n){forn(index_ffj,m)cout<<a[index_ffi][index_ffj]<<' ';cout<<endl;}cout<<endl;
#define out(i) cout<<i<<endl;
#define Pi acos(-1.0)
using namespace std;
const int MOD=int(1e9)+7;
const ll MOD64=(ll)(1e18)+7;
const int INF=0x7fffffff;
const ll INF64=0x7fffffffffffffff;
void file()
{
#ifdef _DEBUG
freopen("cin.txt","r",stdin);
#endif
}
const int N = 2e5+10;
vector<pii> a[N];
int ans[N];
bool vis[N];
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int n;
scanf("%d",&n);
int x,y;
forn(i,n-1)
{
scanf("%d %d",&x,&y);
a[x].pb(mp(y,i));
a[y].pb(mp(x,i));
}
mem(ans,-1);
if(n==2)
{
printf("0\n");
return 0;
}
int num=0;
fore(i,1,n+1)
{
if(sz(a[i])==1)
{
ans[a[i][0].second]=num;
num++;
}
}
forn(i,n-1){
if(ans[i]==-1)printf("%d\n",num++);
else printf("%d\n",ans[i]);
}
return 0;
}
D. Ehab the Xorcist
题意:给定u和v,找到最短的数组,使得元素的异或和为u,和为v。若没有解,输出-1
题解:1、u>v,不可能存在异或和大于和的情况,没有解
2、u==v==0,输出0
3、u==v!=0,数组为{u}
4、由于是异或,从2进制的角度来考虑。
如果u的第i位为1,那么结果的所有元素的第i位为1的个数必定是奇数个
为0, 偶数个
那么把这些位提出来,和刚好为u,剩下的值的异或和必须为0,和为v-u
那么把v-u除以2,如果没有余数,则刚好满足,如果由余数,则无法满足,没有解
再考虑将u的值和(v-u)/2合并,如果没有进位,则可以合并,否则不行
#include<bits/stdc++.h>
#define ll long long int
#define _DEBUG
#define vi vector<int>
#define vl vector<ll>
#define vvi vector<vi>
#define pii pair<int,int>
#define pll pair<ll,ll>
#define pil pair<int,ll>
#define pli pair<ll,int>
#define pb push_back
#define mp make_pair
#define fore(index_i,index_l,index_r) for(int index_i=int(index_l);index_i<int(index_r);index_i++)
#define forn(i,n) fore(i,0,n)
#define sz(a) (int)(a).size()
#define all(a) (a).begin(),(a).end()
#define mem(a,i) memset(a,i,sizeof(a))
#define fout(a,n) forn(index_fi,n)cout<<a[index_fi]<<' ';cout<<endl;
#define ffout(a,n,m) forn(index_ffi,n){forn(index_ffj,m)cout<<a[index_ffi][index_ffj]<<' ';cout<<endl;}cout<<endl;
#define out(i) cout<<i<<endl;
#define Pi acos(-1.0)
using namespace std;
const int MOD=int(1e9)+7;
const ll MOD64=(ll)(1e18)+7;
const int INF=0x7fffffff;
const ll INF64=0x7fffffffffffffff;
void file()
{
#ifdef _DEBUG
freopen("cin.txt","r",stdin);
#endif
}
const int N = 1e5+10;
ll fp[70];
void init()
{
fp[0]=1;
fore(i,1,61)fp[i]=fp[i-1]<<1;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
ll u,v;
cin>>u>>v;
init();
if(u>v)
{
cout<<-1<<endl;
return 0;
}
if(u==v)
{
if(u==0)cout<<0<<endl;
else
cout<<1<<endl<<u<<endl;
return 0;
}
ll a=0,b=0,c=0;
ll tv=v-u;
if(tv%2==1)
{
cout<<-1<<endl;
return 0;
}
a=b=tv/2;
forn(i,61)
{
if(fp[i]>u)break;
if(fp[i]&u)
{
if(fp[i]&a)
c+=fp[i];
else a+=fp[i];
}
}
if(c==0)cout<<2<<endl<<a<<' '<<b<<endl;
else cout<<3<<endl<<a<<' '<<b<<' '<<c<<endl;
return 0;
}
E. Ehab’s REAL Number Theory Problem
题意:给出n个元素组成的数组,每个元素最多只有7个因子,找到最短的子序列,使得子序列中元素之积为平方数。
输出子序列的长度
题解:首先将每个元素考虑成多个质数之和
每个元素最多只有7个因子,即每个元素最多由两个质数组成。
如果有3个,即u=a*b*c,那么公因子有1,a,b,c,a*b,a*c,b*c,u, 一共八个
将元素中的平方数因子提出来,剩下的只有1,p,p*q,q和p都是质数。如果有1,那么答案就是这个数了
那么将每个质数看成是一个点,再加上1这个点,那么对于每个元素,都看成是图上两个点的积,
即将这两个点,连接起来。
那么题目就变成了,在这个图上的最小循环。
题目的范围是n=O(10^5),每个元素x=O(10^6),
10^6以内的质数个数是O(10^4) (9000多个),不可能用Dijkstra算法来做(O(10^4^3)),
这里考虑一个优化,大于1000的质数之间,是不存在边的
那么我们用1000以内的质数,来作为源点,来做bfs,(O(10^3*10^5))
#include<bits/stdc++.h>
#define ll long long int
#define _DEBUG
#define vi vector<int>
#define vl vector<ll>
#define vvi vector<vi>
#define pii pair<int,int>
#define pll pair<ll,ll>
#define pil pair<int,ll>
#define pli pair<ll,int>
#define pb push_back
#define mp make_pair
#define fore(index_i,index_l,index_r) for(int index_i=int(index_l);index_i<int(index_r);index_i++)
#define forn(i,n) fore(i,0,n)
#define sz(a) (int)(a).size()
#define all(a) (a).begin(),(a).end()
#define mem(a,i) memset(a,i,sizeof(a))
#define fout(a,n) forn(index_fi,n)cout<<a[index_fi]<<' ';cout<<endl;
#define ffout(a,n,m) forn(index_ffi,n){forn(index_ffj,m)cout<<a[index_ffi][index_ffj]<<' ';cout<<endl;}cout<<endl;
#define out(i) cout<<i<<endl;
#define Pi acos(-1.0)
using namespace std;
const int MOD=int(1e9)+7;
const ll MOD64=(ll)(1e18)+7;
const int INF=0x7fffffff;
const ll INF64=0x7fffffffffffffff;
void file()
{
#ifdef _DEBUG
freopen("cin.txt","r",stdin);
#endif
}
const int N = 1e6+10;
int d[N],pr[N];
int one_p[N];
int dist[N][2];
int ans = N;
queue<int> q;
vi g[N];
int n;
void init()
{
n=0;
mem(d,-1);
fore(i,2,N)
{
if(d[i]!=-1)continue;
pr[n]=i;
for(int j=i;j<N;j+=i)
{
if(d[j]==-1)
d[j]=n;
}
n++;
}
}
void bfs(int root)
{
while(!q.empty())
{
int v=q.front();
q.pop();
forn(i,sz(g[v]))
{
int u=g[v][i];
if(u==root)continue;
if(dist[u][1]==-1)
{
dist[u][0]=dist[v][0]+1;
dist[u][1]=dist[v][1];
q.push(u);
}
else if(dist[u][1]!=dist[v][1])
{
ans=min(ans,dist[v][0]+dist[u][0]+3);
}
}
}
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
init();
int m;
cin>>m;
forn(i,m)
{
int x;
cin>>x;
vi a;
while(x>1)
{
int id=d[x];
int t=0;
while(x%pr[id]==0)
{
t^=1;
x=x/pr[id];
}
if(t==1)a.pb(id);
}
if(sz(a)==0)
ans=1;
else if(sz(a)==1)
one_p[a[0]]++;
else if(sz(a)==2)
{
g[a[0]].pb(a[1]);
g[a[1]].pb(a[0]);
}
}
if(ans==1)
{
cout<<"1\n";
return 0;
}
forn(i,n)
{
if(one_p[i]>=2)
{
cout<<"2\n";
return 0;
}
}
while(!q.empty())q.pop();
forn(i,n)
{
dist[i][0]=N;
dist[i][1]=-1;
if(one_p[i]>0)
{
dist[i][0]=0;
dist[i][1]=i;
q.push(i);
}
}
bfs(-1);
forn(i,n)
{
if(pr[i]*pr[i]>N)break;
while(!q.empty())q.pop();
forn(j,n)
{
dist[j][0]=N;
dist[j][1]=-1;
}
forn(j,sz(g[i]))
{
int u=g[i][j];
if(dist[u][0]!=N)
{
ans=min(ans,2);
continue;
}
dist[u][0]=0;
dist[u][1]=u;
q.push(u);
}
bfs(i);
}
if(ans==N)ans=-1;
cout<<ans<<endl;
return 0;
}
F.Ehab’s Last Theorem
题意:给定一个n个点,m条边的无向图,sq=⌈√n⌉ .考虑两个问题:
1、是否存在个数刚好为sq的独立数组,即数组元素两两没有边相连
2、是否存在节点数不少于sq的简单环,环上每个点都只经过一次
保证没有自循环和重复边,且图已连接,选择一个问题并给出答案
题解:dfs找环,bfs找独立数组
(吐槽一下,这道题明显比E题要难一点,E题还要建模)
#include<bits/stdc++.h>
#define ll long long int
#define _DEBUG
#define vi vector<int>
#define vl vector<ll>
#define vvi vector<vi>
#define pii pair<int,int>
#define pll pair<ll,ll>
#define pil pair<int,ll>
#define pli pair<ll,int>
#define pb push_back
#define mp make_pair
#define fore(index_i,index_l,index_r) for(int index_i=int(index_l);index_i<int(index_r);index_i++)
#define forn(i,n) fore(i,0,n)
#define sz(a) (int)(a).size()
#define all(a) (a).begin(),(a).end()
#define mem(a,i) memset(a,i,sizeof(a))
#define fout(a,n) forn(index_fi,n)cout<<a[index_fi]<<' ';cout<<endl;
#define ffout(a,n,m) forn(index_ffi,n){forn(index_ffj,m)cout<<a[index_ffi][index_ffj]<<' ';cout<<endl;}cout<<endl;
#define out(i) cout<<i<<endl;
#define Pi acos(-1.0)
using namespace std;
const int MOD=int(1e9)+7;
const ll MOD64=(ll)(1e18)+7;
const int INF=0x7fffffff;
const ll INF64=0x7fffffffffffffff;
void file()
{
#ifdef _DEBUG
freopen("cin.txt","r",stdin);
#endif
}
const int N = 1e6+10;
vi v[N];
int sq,dep[N];
bool mark[N];
int n,m;
stack<int> s;
void dfs(int x)
{
s.push(x);
dep[x]=s.size();
forn(i,sz(v[x]))
{
int u=v[x][i];
if(!dep[u])dfs(u);
else if(dep[x]-dep[u]+1>=sq)
{
cout<<2<<endl<<dep[x]-dep[u]+1<<endl;
fore(i,dep[u]-1,dep[x])
{
int y=s.top();
s.pop();
cout<<y<<' ';
}
cout<<endl;
exit(0);
}
}
if(!mark[x])
{
forn(i,sz(v[x]))
mark[v[x][i]]=true;
}
s.pop();
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n>>m;
int x,y;
forn(i,m)
{
cin>>x>>y;
v[x].pb(y);
v[y].pb(x);
}
mem(mark,false);
mem(dep,0);
sq=0;
while(sq*sq<n)sq++;
dfs(1);
cout<<1<<endl;
for(int i=1;sq;i++)
{
if(!mark[i])
{
cout<<i<<' ';
sq--;
}
}
cout<<endl;
return 0;
}