zoukankan      html  css  js  c++  java
  • BZOJ3837 : [Pa2013]Filary

    当m取2时,k至少为$frac{n}{2}$

    所以在最优解中每个数被选中的概率至少为$frac{1}{2}$

    每次随机选取一个位置i,计算出其它数与$a_i$的差值,将差值分解质因数

    所有质因数中出现次数的最大值加上与$a_i$相等的数的个数就是选取i的情况下的最优解

    为了最大化m,需要将所有相同位置的因数乘起来

    给每个位置随机一个权值,全部异或起来求出Hash值,排序后扫一遍统计即可

    因为$a_ileq10^7$,所以可以先一遍线性筛求出每个数是被哪个素数筛掉的,这样就可以做到$O(log n)$分解质因数

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int N=100010,M=10000001,P=664600;
    int n,i,j,x,a[N],b[N],maxv,p[P],tot,ans1,ans2,T,cnt,pos[P],las[P],now,v[M],tmp[32],fac,vis[P];
    struct PI{
      int cnt,hash,num;
      PI(){cnt=hash=0;num=1;}
      PI(int _cnt,int _hash,int _num){cnt=_cnt,hash=_hash,num=_num;}
    }pool[P];
    inline bool cmp(PI a,PI b){return a.hash<b.hash;}
    inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
    inline void divide(int x,int y){
      int i,j,k;
      for(i=0;i<fac;i++)vis[tmp[i]]=0;
      for(fac=0;x^1;vis[v[x]]*=p[v[x]],x/=p[v[x]])if(!vis[v[x]])tmp[fac++]=v[x],vis[v[x]]=1;
      for(i=0;i<fac;i++){
        k=vis[tmp[i]];
        if(las[tmp[i]]^T)las[tmp[i]]=T,pool[j=pos[tmp[i]]=++now]=PI(0,0,k);else j=pos[tmp[i]];
        pool[j].cnt++,pool[j].hash^=y;
        if(pool[j].num>k)pool[j].num=k;
      }
    }
    int main(){
      pool[0].hash=-1;
      for(read(n);i<n;i++){
        read(a[i]);
        while(!b[i])b[i]=rand();
        if(a[i]>maxv)maxv=a[i];
      }
      for(i=2;i<=maxv;i++){
        if(!v[i])p[v[i]=++tot]=i;
        for(j=1;j<=tot;j++){
          if(i*p[j]>maxv)break;
          v[i*p[j]]=j;
          if(i%p[j]==0)break;
        }
      }
      for(T=1;T<=4;T++){
        for(x=a[rand()%n],i=cnt=now=0;i<n;i++)if(a[i]!=x)divide(a[i]>x?(a[i]-x):(x-a[i]),b[i]);else cnt++;
        sort(pool+1,pool+now+1,cmp);
        for(j=0,i=1;i<=now;i++)if(pool[i].hash^pool[j].hash){
          if(j){
            if(pool[j].cnt+cnt>ans1)ans1=pool[j].cnt+cnt,ans2=pool[j].num;
            else if(pool[j].cnt+cnt==ans1&&pool[j].num>ans2)ans2=pool[j].num;
          }
          j=i;
        }else pool[j].num*=pool[i].num;
        if(pool[j].cnt+cnt>ans1)ans1=pool[j].cnt+cnt,ans2=pool[j].num;
        else if(pool[j].cnt+cnt==ans1&&pool[j].num>ans2)ans2=pool[j].num;
      }
      return printf("%d %d",ans1,ans2),0;
    }
    

      

  • 相关阅读:
    Velocity的使用小记
    fastJson的SerializeFilter使用
    快捷的时间转化
    How to execute a Stored Procedure with Entity Framework Code First
    自定义 ASP.NET Identity Data Model with EF
    Asp.Net Core get client IP
    HTTP 请求头中的 X-Forwarded-For
    HttpRequest,WebRequest,HttpWebRequest,WebClient,HttpClient 之间的区别
    【逻辑】500桶酒,找毒酒
    Asp.Net Core 输出 Word
  • 原文地址:https://www.cnblogs.com/clrs97/p/4403132.html
Copyright © 2011-2022 走看看