解法:
首先判断无解的情况:
1.易得m为奇数时无解
2.大于最大组数4*n时无解
3.小于最小组数时无解 :
接下来构造合法情况:
采用不断从最小组合情况里从上到下的顺序不断拆出,放到遥远处,使得组合数为m
每次拆一个正方形组合数加num
当该正方形的四个方向有2个正方形相邻时,num=4;
当该正方形的四个方向只有1个正方形相邻时,num=2;
当出现还差2个组合数时,需要特殊处理:
假设现在轮到( i , j )位置正方形拆开时,若增加的num=2 ,则放到遥远处
若num=4 ,则会多加2个组合,可以构造放到(1,1)位置的左边,就可以时增加的num降至2
即可
#include<bits/stdc++.h> using namespace std; int t; int n,m; int aa,bb; int getmin(int a)//最小组合数 { int ans=1e9; for(int i=1;i<=a;i++) { int j=(int)ceil((double)a/i); if(i+j<=ans&&i&&j&&abs(i-j)<=1) { aa=i; bb=j; if(aa>bb) swap(aa,bb); } ans=min(ans,i+j); } return 2*ans; } int main() { scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); if(m%2||m>4*n||getmin(n)>m)//无解 { printf("No\n"); } else { int mi=getmin(n);//最小组合数 vector<pair<int,int> > v; vector<pair<int,int> > u; int num=n; for(int i=1;i<=aa&#i++) { for(int j=1;j<=bb&#j++) { v.push_back(make_pair(i,j));//按最小的方式构造 再拆开 num--; } } int now=n-1; int flag=1; while(m - mi >= 4&&now>=0) { int x=v[now].first; int y=v[now].second; if(y==1||x==1) { mi+=2; } else mi+=4; u.push_back(make_pair(flag,100000000));//放到遥远处 now--; flag+=2; if(mi==m) break; } if(m-mi==2) { int x=v[now].first; int y=v[now].second; if(y==1||x==1) { u.push_back(make_pair(flag,100000000));//放到遥远处 } else { u.push_back(make_pair(0,1));//放到(1,1)旁边 } now--; } puts("Yes"); for(int i=0;i<v.size()-u.size();i++) { auto T=v[i]; printf("%d %d\n",T.first,T.second); } for(auto T:u) { printf("%d %d\n",T.first,T.second); } } } }
解法:
情况1:先考虑能不能通过构造出c,d,e,f 我们可以构造出一左边分数减去右边分数就是a/b,例如:
但是由于存在限制条件d,f<b ,此需要约分变化一下,若gcd(a,b)!=1 ,则b=b/gcd,就满足该限制了
、、 此时B<b了
情况2:当不满足情况1时,说明一定gcd(a,b)==1 ,若b==1或b为素数(相异质因数),那么无解 -1 -1 -1 -1
情况3:当d*f=b,且d,f互质 通分得:
再拓展gcd即可
#include<bits/stdc++.h> #define ll long long using namespace std; void exgcd(ll a,ll b,ll &d,ll &x,ll &y) { if(!b) { d=a; x=1; y=0; } else { exgcd(b,a%b,d,y,x); y-=x*(a/b); } } ll mod_count(ll a,ll c,ll b)//求解模线性方程ax=c(mod b) { ll x,y; ll gcd; exgcd(a,b,gcd,x,y); ll aa=a; ll bb=b; while(x<=0||y>=0)//注意x,y 符号 { x+=bb; y-=aa; } x=(x*(c/gcd));//次题gcd一定为1 y=(y*(c/gcd)); printf("%lld %lld %lld %lld\n",x,bb,-1*y,aa); return x; } const int N=2e6+5; int mark[N]; int prim[N]; int cnt; void initial() { cnt=0; for (int i=2 ; i<N ; ++i) { if (mark[i]==0) prim[cnt++]=i; for (ll j=1ll*i*i;j<N;j+=i) { if(mark[j]==0) mark[j]=i; else mark[j]=min(mark[j],i); } } } int main() { initial(); int t; scanf("%d",&t); while(t--) { ll A,B; scanf("%lld%lld",&A,&B); ll gcd=__gcd(A,B); if(gcd!=1)//先后!!! { A/=gcd; B/=gcd; printf("%lld %lld %lld %lld\n",A+1,B,1ll,B); continue; } if(B==1||!mark[B]) { printf("-1 -1 -1 -1\n"); continue; } int flag=0; ll d,f; d=mark[B]; f=B/d; while(f%mark[B]==0) { d*=mark[B]; f/=mark[B]; } if(f==1) { printf("-1 -1 -1 -1\n"); continue; } // printf("f=%lld !",f); mod_count(f,A,d); } }
#include<bits/stdc++.h> using namespace std; int fa[800005]; int color[800005]; list<int> L[800005]; vector<int> G[800005]; int find(int x) { if(fa[x]==x) return fa[x]; else return fa[x]=find(fa[x]); } int main() { int t; scanf("%d",&t); while(t--) { int n,m; scanf("%d%d",&n,&m); for(int i=0;i<=n;i++) { fa[i]=i; L[i].clear(); G[i].clear(); L[i].push_back(i); } for(int i=0;i<m;i++) { int u,v; scanf("%d%d",&u,&v) ; G[u].push_back(v); G[v].push_back(u); } int Q; scanf("%d",&Q); while(Q--) { int x; scanf("%d",&x); if(fa[x]!=x) continue; //int fx=find(x); int cnt=L[x].size(); while(cnt--) { int y=L[x].front(); L[x].pop_front(); for(auto T:G[y]) { int fT=find(T); if(fT!=x) { fa[fT]=x; L[x].splice(L[x].end(),L[fT]); } } } } for(int i=0;i<n;i++) { printf("%d ",find(i)); } puts(""); } }
2020牛客暑期多校训练营(第三场)D、E、F
最新推荐文章于 2020-07-30 12:42:06 发布