codeforces 628.div2
生活随笔
收集整理的這篇文章主要介紹了
codeforces 628.div2
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
# Codeforces 628.div2
- A. EhAb AnD gCd
- B. CopyCopyCopyCopyCopy
- C. Ehab and Path-etic MEXs
- D. Ehab the Xorcist
- E. Ehab's REAL Number Theory Problem
- F.Ehab's Last Theorem
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 _DEBUGfreopen("cin.txt","r",stdin);// freopen("cout.txt","w",stdout); #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 _DEBUGfreopen("cin.txt","r",stdin);// freopen("cout.txt","w",stdout); #endif } /* 1、MEX(u,v)=i,代表u~v的簡單路徑上,包含0、1...i-1,那么用貪心的思想讓小的自然數之間的路徑,盡可能的少,且在不同的路徑上,即把他們放在葉節點上 */ 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,輸出03、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 _DEBUGfreopen("cin.txt","r",stdin);// freopen("cout.txt","w",stdout); #endif }const int N = 1e5+10; ll fp[70];void init()//fp[i]=2^i {fp[0]=1;fore(i,1,61)fp[i]=fp[i-1]<<1;//fout(fp,61); }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;elsecout<<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)//如果u的第i位為1 {if(fp[i]&a)//如果(v-u)/2的第i位為1,則無法合并, 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 _DEBUGfreopen("cin.txt","r",stdin);// freopen("cout.txt","w",stdout); #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()//求10^6以內的質數,pr[i]表示第i個質數是pr[i],總共n個,//d[j]表示j的最小質數在pr數組中的坐標 {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;//異或來表示個數,1:奇數個,0:偶數個 x=x/pr[id];}if(t==1)a.pb(id);}if(sz(a)==0)//x剛好為平方數 ans=1;else if(sz(a)==1)//x=1*a[0] one_p[a[0]]++;else if(sz(a)==2)//x=a[0]*a[1]{g[a[0]].pb(a[1]);g[a[1]].pb(a[0]);}//cout<<i<<' ';fout(a,sz(a));}if(ans==1){cout<<"1\n";return 0;}forn(i,n){if(one_p[i]>=2)//存在兩個1*one_p[i] {cout<<"2\n";return 0;}}//out(1);//當1做為源點時 while(!q.empty())q.pop();forn(i,n){//out(i);dist[i][0]=N;//dist[i][0]表示第i個質數到源點的距離 dist[i][1]=-1;//dist[i][1]表示第i個質數屬于源點的哪一個子節點 if(one_p[i]>0){dist[i][0]=0;//這里為0,和后面出現環的時候的+3對應 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 _DEBUGfreopen("cin.txt","r",stdin);// freopen("cout.txt","w",stdout); #endif }const int N = 1e6+10; vi v[N]; int sq,dep[N]; bool mark[N];//標記數組,標記為1表示不要,為0表示要 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)//出現環,且環的長度大于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])//對于要的節點,給相連的節點上標記1,保證不會出現要的點相連, {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; }總結
以上是生活随笔為你收集整理的codeforces 628.div2的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: DisplayTag详解
- 下一篇: 用过滤器实现file类实现输出目录以及子