• [校内训练20_01_22]ABC


    1.给出序列A,求序列B,使得bi|ai,lcm(b1,b2,...,bn)=lcm(a1,a2,...,an)且字典序最小。

    可以发现,对于某个质数p,它有一个最大的次数k将pk放在尽可能靠后且能够整除原数组中的数字的位置上,便是答案。

    虽然数字的值域达到1E18,但我们只需要知道每个数1~1E6之间的质因子是什么以及是哪些,剩下来的一定是大于1E6的质因子且最多只有两个。

    由于答案中的质数及其次数彼此间相互独立,1E6以下的质因子可以直接统计,而剩下的可以通过两两间求gcd的方法进行比较。在这种情况下,数字ABA在原数组的前面,B在后面)由于质数次数最多为2,令x=gcd(A,B)B除以x后(对于某个质因子)要么次数为0,要么为1,要么为22要特判一下,如果有这种情况,B要更新当且仅当A==B),乘上gcd(x,B除以x)后即可进行更新。复杂度为O(n2*logMAX+MAX0.333)

    当然,若不嫌麻烦的话可套用pollard-rho模板。复杂度为O(n*MAX0.25)

    博主在考场上采用了后者。

     1 #include <cstdio>
     2 #include <sstream>
     3 #include <iostream>
     4 #include <algorithm>
     5 
     6 using namespace std;
     7 
     8 typedef long long LL;
     9 
    10 const int MAXN = 105;
    11 
    12 LL num[MAXN];
    13 LL common[MAXN];
    14 int n, cs;
    15 
    16 LL gcd(LL a, LL b)
    17 {
    18     LL tmp;
    19     while (b) tmp = a, a = b, b = tmp % b;
    20     return a;
    21 }
    22 
    23 void solve()
    24 {
    25     for (int i = 0; i < n; i++){
    26         cs = 0;
    27         for (int j = 0; j < n; j++)
    28             if (i != j)
    29                 common[cs ++] = gcd(num[i], num[j]);
    30         LL s = 1;
    31         for (int j = 0; j < cs; j++){
    32             s *= common[j];
    33             for (int k = j+1; k < cs; k++)
    34                 common[k] /= gcd(common[j], common[k]);
    35          }
    36          num[i] /= s;
    37          while (true){
    38             LL x = gcd(num[i], s);
    39             if (x == 1)
    40                 break;
    41             num[i] *= x;
    42             s /= x;
    43         }
    44     }
    45 }
    46 
    47 int main()
    48 {
    49     freopen("transform.in", "r", stdin);
    50     freopen("transform.out", "w", stdout);
    51     scanf("%d", &n);
    52     for (int i = 0; i < n; i ++)
    53         scanf("%lld", &num[i]);
    54     solve();
    55     for (int i = 0; i < n; i ++)
    56         printf("%lld ", num[i]);
    57     printf("
    ");
    58     return 0;
    59 }
    View Code
      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 typedef long long int ll;
      4 typedef long double ld;
      5 ll n,a[105],ans[105];
      6 map<ll,ll>cnt,where;
      7 namespace math
      8 {
      9     const int len=10;
     10     ll test[len]={2,3,5,7,11,13,17,19,23,29};
     11     ll size,wait[555];
     12     inline ll mul(ll x,ll y,ll mod)
     13     {
     14         ll d=(ld)x*y/mod;
     15         return ((x*y-d*mod)%mod+mod)%mod;
     16     }
     17     inline ll QPOW(ll x,ll y)
     18     {
     19         ll ans=1;
     20         for(int i=1;i<=y;++i)
     21             ans=ans*x;
     22         return ans;
     23     }
     24     inline ll qpow(ll x,ll y,ll mod)
     25     {
     26         ll ans=1,base=x;
     27         while(y)
     28         {
     29             if(y&1)
     30                 ans=mul(ans,base,mod);
     31             base=mul(base,base,mod);
     32             y>>=1;
     33         }
     34         return ans;
     35     }
     36     inline bool isPrime(ll p)
     37     {
     38         for(int i=0;i<len;++i)
     39         {
     40             if(p<test[i])
     41                 return false;
     42             else if(p==test[i])
     43                 return true;
     44             ll x=qpow(test[i],p-1,p),d=p-1;
     45             if(x!=1)
     46                 return false;
     47             while(x==1&&d%2==0)
     48             {
     49                 d>>=1;
     50                 x=qpow(test[i],d,p);
     51                 if(x!=1&&x!=p-1)
     52                     return false;
     53             }
     54         }
     55         return true;
     56     }
     57     ll gcd(ll x,ll y)
     58     {
     59         if(y==0)
     60             return x;
     61         return x%y==0?y:gcd(y,x%y);
     62     }
     63     inline ll f(ll x,int c,ll mod)
     64     {
     65         return (mul(x,x,mod)+c)%mod;
     66     }
     67     inline ll find(ll n,int step,int c)
     68     {
     69         if(n%2==0)
     70             return 2;
     71         ll x=2,y=2,d=1;
     72         while(true)
     73         {
     74             ll tmpX=x,tmpY=y,d=1;
     75             for(int i=1;i<=step;++i)
     76             {
     77                 x=f(x,c,n);
     78                 y=f(f(y,c,n),c,n);
     79                 d=mul(d,(x%n-y%n+n)%n,n);
     80             }
     81             d=gcd(d,n);
     82             if(d==1)
     83                 continue;
     84             else if(d!=n)
     85                 return d;
     86             x=tmpX,y=tmpY;
     87             for(int i=1;i<=step;++i)
     88             {
     89                 x=f(x,c,n);
     90                 y=f(f(y,c,n),c,n);
     91                 d=gcd(n,(x%n-y%n+n)%n);
     92                 if(d!=1&&d!=n)
     93                     return d;
     94             }
     95             return 0;
     96         }
     97         return -1;
     98     }
     99     void factor(ll x)
    100     {
    101         if(isPrime(x))
    102         {
    103             wait[++size]=x;
    104             return;
    105         }
    106         ll step=pow(x,0.1)+1,c=0,now=0;
    107         while(!now)
    108             now=find(x,step,++c);
    109         factor(now),factor(x/now);
    110     }
    111     void pollard(ll x,int num)
    112     {
    113         size=0;
    114         factor(x);
    115         map<ll,ll>G;
    116 //        for(int i=1;i<=size;++i)
    117 //            cout<<wait[i]<<" ";
    118 //        cout<<endl;
    119         for(int i=1;i<=size;++i)
    120             ++G[wait[i]];
    121         for(int i=1;i<=size;++i)
    122         {
    123             x=wait[i];
    124             if(G[x]>=cnt[x])
    125             {
    126                 ans[where[x]]/=QPOW(x,cnt[x]);
    127                 cnt[x]=G[x];
    128                 where[x]=num;
    129                 ans[num]*=QPOW(x,cnt[x]);
    130             }
    131         }
    132     }
    133 }
    134 inline bool check(int x)
    135 {
    136     if(x==1)
    137         return false;
    138     for(int i=2;i*i<=x;++i)
    139         if(x%i==0)
    140             return false;
    141     return true;
    142 }
    143 int main()
    144 {
    145     freopen("transform.in","r",stdin);
    146     freopen("transform.out","w",stdout);
    147     ios::sync_with_stdio(false);
    148     cin>>n;
    149     for(int i=1;i<=n;++i)
    150     {
    151         cin>>a[i];
    152         ans[i]=1;
    153         math::pollard(a[i],i);
    154     }
    155     for(int i=1;i<=n;++i)
    156         cout<<ans[i]<<" ";
    157     cout<<endl;
    158     return 0;
    159 }
    View Code

    2.有一些机场和航线,航线是形如点A到点B的直线,飞机会准时从t1出发t2到达,期间匀速直线运动。机场和飞机都配备雷达,雷达有固定范围R,你需要保证在任意时间内,任意在飞行中的飞机能够通过雷达直接或间接地与机场相连,求最小的R。

      我们先二分半径r,考虑怎么进行检验。可以发现,不管是飞机关于机场、飞机关于飞机,它们能相互建立连接的可行时间点组成了一个区间,因此一个想法为求出这个区间,对于特定的端点建图进行检查。

    对于飞机关于机场的情况是简单的。根据普通的平面向量知识,可以轻松地求出这个向量(飞机的飞行路线)与圆(圆心机场,半径为r)的两个交点(如果存在的话)。再次利用数量积的知识,可以知道这两个点到出发点的距离,与整个路线长度的比值(当然,这是有方向的)。求完后分别取minmax保证时间确实在航班时间范围内即可(比如说起点在圆里面的情况)。

    飞机关于飞机比较麻烦。首先,我们先使得航线A和航线B的速度相等,这样方便下面求解。具体地讲,A向量的模除以时间A的值,要等于B向量的模除以时间的值。然后以飞机A为参考系,飞机B的航线路线就变为B-A。剩下的操作与“飞机关于机场”的完全一致,只不过要保证时间要在两个航班时间范围内。

    还有一点要注意的是,向量可能经过圆心,这需要判断。

    总共有O((n+m)2)个区间,单次建边、检查的复杂度是O((n+m)2)的,因此总复杂度为O((n+m)4logn)

     

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 typedef long double ld;
      4 const ld eps=1E-9;
      5 const ld inf=1E12;
      6 int n,m;
      7 int A[555],B[555];
      8 ld from[555],to[555],length[555];
      9 struct pt
     10 {
     11     ld x,y;
     12     pt(ld a=0,ld b=0):x(a),y(b){}
     13     pt operator+(const pt&A){return pt(x+A.x,y+A.y);}
     14     pt operator-(const pt&A){return pt(x-A.x,y-A.y);}
     15     pt operator*(const ld&d){return pt(x*d,y*d);}
     16     pt operator/(const ld&d){return pt(x/d,y/d);}
     17     ld operator*(const pt&A){return x*A.y-y*A.x;}
     18     ld operator&(const pt&A){return x*A.x+y*A.y;}
     19     void out()
     20     {
     21         cout<<"("<<x<<","<<y<<")";
     22     }
     23 }p[555];
     24 struct line
     25 {
     26     pt A,B;
     27     line(pt a=pt(),pt b=pt()):A(a),B(b){}
     28 };
     29 struct info
     30 {
     31     ld L,R;
     32     int x,y;
     33     info(ld a=0,ld b=0,int c=0,int d=0):L(a),R(b),x(c),y(d){}
     34 }tmp[555555];
     35 inline ld s(ld x){return x*x;}
     36 inline pt intersection(line a,line b)
     37 {
     38     pt A=b.B-b.A,B=a.B-a.A,C=b.A-a.A;
     39     if(abs(A*B)<=eps)
     40         return pt(inf,inf);
     41     ld d=-(B*C)/(B*A);
     42     return b.A+A*d;
     43 }
     44 inline pt T(pt A)
     45 {
     46     return pt(-A.y,A.x);
     47 }
     48 inline pt perpendicular(pt A,line a)
     49 {
     50     if(abs((A-a.A)*(A-a.B))<=eps)
     51         return A;
     52     pt B=A+T(a.B-a.A);
     53     return intersection(line(A,B),a);
     54 }
     55 inline ld dis(pt A,pt B)
     56 {
     57     return sqrt(s(A.x-B.x)+s(A.y-B.y));
     58 }
     59 namespace graph
     60 {
     61     int size,head[555555];
     62     bool vis[55555];
     63     struct edge
     64     {
     65         int to,next;
     66     }E[555555];
     67     inline void clear()
     68     {
     69         for(int i=1;i<=n+m;++i)
     70             head[i]=0;
     71         for(int i=1;i<=size;++i)
     72             E[i].to=E[i].next=0;
     73         size=0;
     74     }
     75     inline void add(int u,int v)
     76     {
     77         E[++size].to=v;
     78         E[size].next=head[u];
     79         head[u]=size;
     80     }
     81     inline bool ok(ld x)
     82     {
     83         for(int i=1;i<=n+m;++i)
     84             vis[i]=0;
     85         queue<int>Q;
     86         for(int i=1;i<=n;++i)
     87         {
     88             Q.push(i);
     89             vis[i]=1;
     90         }
     91         while(!Q.empty())
     92         {
     93             int u=Q.front();
     94             Q.pop();
     95             for(int i=head[u];i;i=E[i].next)
     96             {
     97                 int v=E[i].to;
     98                 if(vis[v])
     99                     continue;
    100                 Q.push(v);
    101                 vis[v]=1;
    102             }
    103         }
    104         for(int i=n+1;i<=n+m;++i)
    105             if((!vis[i])&&(from[i-n]-eps<=x&&x<=to[i-n]+eps))
    106                 return false;
    107         return true;
    108     }
    109 }
    110 int tot;
    111 inline bool test(ld x)
    112 {
    113     graph::clear();
    114     for(int i=1;i<=tot;++i)
    115         if(tmp[i].L-eps<=x&&x<=tmp[i].R+eps)
    116         {
    117             graph::add(tmp[i].x,tmp[i].y);
    118             graph::add(tmp[i].y,tmp[i].x);
    119         }
    120     return graph::ok(x);
    121 }
    122 inline bool check(ld r)
    123 {
    124     tot=0;
    125     for(int i=1;i<=n;++i)
    126     {
    127         pt O=p[i];
    128         for(int j=1;j<=m;++j)
    129         {
    130             line a(p[A[j]],p[B[j]]);
    131             pt P=perpendicular(O,a),D,pA,pB;
    132             ld d=s(P.x-O.x)+s(P.y-O.y);
    133             if(d>r*r-eps)
    134                 continue;
    135             else if(abs(d)<=eps)
    136                 D=(a.B-a.A)*r/dis(a.A,a.B);
    137             else
    138                 D=T((P-O)*sqrt(r*r/d-1));
    139             pA=P+D,pB=P-D;
    140             ld t1=((pA-p[A[j]])&(p[B[j]]-p[A[j]]))/length[j]/length[j]*(to[j]-from[j])+from[j];
    141             ld t2=((pB-p[A[j]])&(p[B[j]]-p[A[j]]))/length[j]/length[j]*(to[j]-from[j])+from[j];
    142             if(t1>t2)
    143                 swap(t1,t2);
    144             t1=max(from[j],t1);
    145             t2=min(to[j],t2);
    146             if(t2-t1>=eps)
    147                 tmp[++tot]=info(t1,t2,i,n+j);
    148         }
    149     }
    150     for(int i=1;i<=m;++i)
    151         for(int j=1;j<=m;++j)
    152         {
    153             if(from[i]<=from[j])
    154                 continue;
    155             ld delT=from[i]-from[j];
    156             ld g=(ld)(to[i]-from[i])/(ld)(to[j]-from[j]-delT);
    157             pt I=p[A[i]]-p[B[i]];
    158             pt J=(p[B[j]]-p[A[j]])*delT/(to[j]-from[j]);
    159             line a(p[A[j]]+J,p[A[j]]+J+I+(p[B[j]]-(p[A[j]]+J))*g);
    160             pt O=p[A[i]];
    161             pt P=perpendicular(O,a),D,pA,pB;
    162             ld d=s(P.x-O.x)+s(P.y-O.y);
    163             if(d>r*r-eps)
    164                 continue;
    165             else if(abs(d)<=eps)
    166                 D=(a.B-a.A)*r/dis(a.A,a.B);
    167             else
    168                 D=T((P-O)*sqrt(r*r/d-1));
    169             pA=P+D,pB=P-D;
    170             ld len=dis(a.A,a.B);
    171             ld t1=((pA-a.A)&(a.B-a.A))/len/len*(to[i]-from[i])+from[i];
    172             ld t2=((pB-a.A)&(a.B-a.A))/len/len*(to[i]-from[i])+from[i];
    173             if(t1>t2)
    174                 swap(t1,t2);
    175             t1=max(max(from[i],from[j]),t1);
    176             t2=min(min(to[i],to[j]),t2);
    177             if(t2-t1>=eps)
    178                 tmp[++tot]=info(t1,t2,n+i,n+j);
    179         }
    180     for(int i=1;i<=tot;++i)
    181     {
    182         if((!test(tmp[i].L-2*eps))||(!test(tmp[i].R-2*eps)))
    183             return false;
    184         if((!test(tmp[i].L+2*eps))||(!test(tmp[i].R+2*eps)))
    185             return false;
    186     }
    187     return true;
    188 }
    189 int main()
    190 {
    191     freopen("airline.in","r",stdin);
    192     freopen("airline.out","w",stdout);
    193     ios::sync_with_stdio(false);
    194     cin>>n>>m;
    195     for(int i=1;i<=n;++i)
    196         cin>>p[i].x>>p[i].y;
    197     for(int i=1;i<=m;++i)
    198     {
    199         cin>>A[i]>>B[i]>>from[i]>>to[i];
    200         ++A[i],++B[i];
    201     }
    202     for(int i=1;i<=m;++i)
    203         length[i]=dis(p[A[i]],p[B[i]]);
    204     ld L=0,R=0,mid;
    205     for(int i=1;i<=n;++i)
    206         for(int j=i+1;j<=n;++j)
    207             R=max(R,dis(p[i],p[j]));
    208     R*=2;
    209     while(abs(R-L)>0.000001)
    210     {
    211         mid=(L+R)/2;
    212         if(check(mid))
    213             R=mid;
    214         else
    215             L=mid;
    216     }
    217     cout<<fixed<<setprecision(4)<<mid<<endl;
    218     return 0;
    219 }
    View Code

     

     

    我们先

    二分半径r,考虑怎么进行检验。可以发现,不管是飞机关于机场、飞机关于飞机,它们能相互建立连接的可行时间点组成了一个区间,因此一个想法为求出这个区间,对于特定的端点建图进行检查。

    对于飞机关于机场的情况是简单的。根据普通的平面向量知识,可以轻松地求出这个向量(飞机的飞行路线)与圆(圆心机场,半径为r)的两个交点(如果存在的话)。再次利用数量积的知识,可以知道这两个点到出发点的距离,与整个路线长度的比值(当然,这是有方向的)。求完后分别取minmax保证时间确实在航班时间范围内即可(比如说起点在圆里面的情况)。

    飞机关于飞机比较麻烦。首先,我们先使得航线A和航线B的速度相等,这样方便下面求解。具体地讲,A向量的模除以时间A的值,要等于B向量的模除以时间的值。然后以飞机A为参考系,飞机B的航线路线就变为B-A。剩下的操作与“飞机关于机场”的完全一致,只不过要保证时间要在两个航班时间范围内。

    还有一点要注意的是,向量可能经过圆心,这需要判断。

    总共有O((n+m)2)个区间,单次建边、检查的复杂度是O((n+m)2)的,因此总复杂度为O((n+m)4logn)

  • 相关阅读:
    spring
    抽象和封装
    Oracle索引的原理
    使用JdbcTemplate.queryForObject 的注意点
    ORM是什么意思
    Java 后台处理数据库的二进制图片流
    Extjs girdPanel显示图片
    斜率dp
    多重背包的二进制优化
    POJ 3249 DAG图最短路
  • 原文地址:https://www.cnblogs.com/GreenDuck/p/12252853.html
Copyright © 2020-2023  润新知