BZOJ2082 : [Poi2010]Divine divisor

将所有数分解质因数,那么第一问就是求指数的最大值,第二问就是$2^{指数最大的质数个数}-1$。

首先将$10^6$以内的质因数全部找到,那么剩下部分的因子$>10^6$,且只有3种情况:

1.大质数

2.大质数的平方

3.两个大质数的乘积

对于1可以用MillerRabin算法判定,对于2可以尝试开根号然后判定。

那么剩下的一定是3,对于每个不确定的数字,如果它所含的因子只有它有,那么这两个因子可以合并,算第二问的时候个数$+=2$即可。

判断其它数字是否也有这个因子,只需要求gcd即可。

时间复杂度$O(\frac{nv^{\frac{1}{3}}}{\ln v})$。

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstdlib>
using namespace std;
typedef long long ll;
const int N=1000000,B=10000,MAXL=220;
int n,i,j,k,tot,p[N],v[N],ca,cb,cc,ans0,ans1;ll a[64*600],b[610],c[610];
inline ll gcd(ll a,ll b){
  ll c=1;
  while(a-b){
    if(a&1){
      if(b&1){
        if(a>b)a=(a-b)>>1;else b=(b-a)>>1;
      }else b>>=1;
    }else{
      if(b&1)a>>=1;else c<<=1,a>>=1,b>>=1;
    }
  }
  return c*a;
}
inline ll mul(ll a,ll b,ll n){return(a*b-(ll)(a/(long double)n*b+1e-3)*n+n)%n;}
inline ll pow(ll a,ll b,ll n){
  ll d=1;a%=n;
  while(b){
    if(b&1)d=mul(d,a,n);
    a=mul(a,a,n);
    b>>=1;
  }
  return d;
}
inline bool check(ll a,ll n){
  ll m=n-1,x,y;int i,j=0;
  while(!(m&1))m>>=1,j++;
  x=pow(a,m,n);
  for(i=1;i<=j;x=y,i++){
    y=pow(x,2,n);
    if((y==1)&&(x!=1)&&(x!=n-1))return 1;
  }
  return y!=1;
}
inline bool miller_rabin(ll n){
  int t=5;ll a;
  if(!(n&1))return 0;
  while(t--)if(check(rand()%(n-1)+1,n))return 0;
  return 1;
}
inline ll getsqrt(ll n){
  ll x=sqrt(n);
  for(ll i=x-2;i<=x+2;i++)if(i*i==n)return i;
  return 0;
}
inline void divide(){
  ll n;
  scanf("%lld",&n);
  for(int i=0;i<tot&&p[i]<=n;i++)while(n%p[i]==0)n/=p[i],a[++ca]=p[i];
  if(n==1)return;
  if(miller_rabin(n)){a[++ca]=c[++cc]=n;return;}
  ll t=getsqrt(n);
  if(t){a[++ca]=t;a[++ca]=c[++cc]=t;return;}
  b[++cb]=n;
}
inline void solve(ll n){
  for(int i=1;i<=cc;i++)if(n%c[i]==0){
    a[++ca]=c[i],a[++ca]=n/c[i];
    return;
  }
  for(int i=1;i<=cb;i++){
    ll t=gcd(n,b[i]);
    if(t==1||t==n)continue;
    a[++ca]=t,a[++ca]=n/t;
    return;
  }
  a[++ca]=-n;
}
struct Num{
  int a[MAXL],len,fu;
  Num(){len=1,fu=a[1]=0;}
  Num operator+(const Num&b){
    Num c;
    c.len=max(len,b.len)+2;
    int i;
    for(i=1;i<=c.len;i++)c.a[i]=0;
    if(fu==b.fu){
      for(i=1;i<=len;i++)c.a[i]=a[i];
      for(i=1;i<=b.len;i++)c.a[i]+=b.a[i];
      for(i=1;i<=c.len;i++)if(c.a[i]>=B)c.a[i+1]++,c.a[i]-=B;
      while(c.len>1&&!c.a[c.len])c.len--;
      c.fu=fu;
    }else{
      bool flag=0;
      if(len==b.len){
        for(i=len;i;i--)if(a[i]!=b.a[i]){
          if(a[i]>b.a[i])flag=1;
          break;
        }
      }else{
        if(len>b.len)flag=1;
      }
      if(flag){
        for(i=1;i<=len;i++)c.a[i]=a[i];
        for(i=1;i<=b.len;i++)c.a[i]-=b.a[i];
        for(i=1;i<=c.len;i++)if(c.a[i]<0)c.a[i+1]--,c.a[i]+=B;
        while(c.len>1&&!c.a[c.len])c.len--;
        c.fu=fu;
      }else{
        for(i=1;i<=b.len;i++)c.a[i]=b.a[i];
        for(i=1;i<=len;i++)c.a[i]-=a[i];
        for(i=1;i<=c.len;i++)if(c.a[i]<0)c.a[i+1]--,c.a[i]+=B;
        while(c.len>1&&!c.a[c.len])c.len--;
        c.fu=b.fu;
      }
    }
    return c;
  }
  void write(){
    printf("%d",a[len]);
    for(int i=len-1;i;i--)printf("%04d",a[i]);
  }
  void set(int x){
    if(x<0){a[len=1]=fu=1;return;}
    fu=0,a[len=1]=x;
  }
}num,sub;
int main(){
  for(i=2;i<N;i++){
    if(!v[i])p[tot++]=i;
    for(j=0;j<tot&&i*p[j]<N;j++){
      v[i*p[j]]=1;
      if(i%p[j]==0)break;
    }
  }
  scanf("%d",&n);
  while(n--)divide();
  for(i=1;i<=cb;i++)solve(b[i]);
  sort(a+1,a+ca+1);
  for(i=1;i<=ca;i=j){
    for(j=i;j<=ca&&a[i]==a[j];j++);
    k=j-i,tot=a[i]<0?2:1;
    if(k>ans0)ans0=k,ans1=tot;else if(k==ans0)ans1+=tot;
  }
  printf("%d\n",ans0);
  num.set(1);
  while(ans1--)num=num+num;
  sub.set(-1);
  num=num+sub;
  num.write();
  return 0;
}

  

时间: 2024-11-01 14:08:28

BZOJ2082 : [Poi2010]Divine divisor的相关文章

[转]分块

转自:https://www.cnblogs.com/Sdchr/p/7927411.html 分块 设阈值 T ,把数据划分为两类,某一类的数据具有某种优势,另外一类的数据又具有另外一种优势,就可以结合利用两种优势,达到更优秀的复杂度.序列分块1. 「TH 2517」数颜色 单点修改,区间不同数个数,强制在线.2. 「SPOJ UNTITLE1」 n <= 5e5 ,区间增加等差数列,区间最值. 区间修改.区间查询是一类经典问题,数据结构的做法通常是划分为若干个子区间,若子区间的信息能够合并,

单调队列 BZOJ 2096 [Poi2010]Pilots

2096: [Poi2010]Pilots Time Limit: 30 Sec  Memory Limit: 162 MBSubmit: 819  Solved: 418[Submit][Status][Discuss] Description Tz又耍畸形了!!他要当飞行员,他拿到了一个飞行员测试难度序列,他设定了一个难度差的最大值,在序列中他想找到一个最长的子串,任意两个难度差不会超过他设定的最大值.耍畸形一个人是不行的,于是他找到了你. Input 输入:第一行两个有空格隔开的整数k(0

BZOJ 2086: [Poi2010]Blocks

2086: [Poi2010]Blocks Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 494  Solved: 222[Submit][Status][Discuss] Description 给出N个正整数a[1..N],再给出一个正整数k,现在可以进行如下操作:每次选择一个大于k的正整数a[i],将a[i]减去1,选择a[i-1]或a[i+1]中的一个加上1.经过一定次数的操作后,问最大能够选出多长的一个连续子序列,使得这个子序列的每个数

BZOJ 2080: [Poi2010]Railway 双栈排序

2080: [Poi2010]Railway Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 140  Solved: 35[Submit][Status][Discuss] Description 一个铁路包含两个侧线1和2,右边由A进入,左边由B出去(看下面的图片) 有n个车厢在通道A上,编号为1到n,它们被安排按照要求的顺序(a1,a2,a3,a4....an)进入侧线,进去还要出来,它们要按照编号顺序(1,2,3,4,5....n)从通道B

BZOJ2086: [Poi2010]Blocks

题解: 想了想发现只需要求出最长的一段平均值>k即可. 平均值的问题给每个数减去k,判断是否连续的一段>0即可. 然后我们发现如果i<j 且 s[i]<s[j],那么 j 对于l>j不会比i 优. 那我们就可以维护一个单调的s[i],然后对于每个l去二分出它的答案. 但这样会T. 再次考虑单调性. 如果 l>j,且s[l]>s[i],那么我们的答案最小也是l-i,所以j必须取比i小的s才有可能更新答案.然后就可以两个指针扫一遍了. 好吧 我承认我口胡... 代码:

洛谷 P3507 [POI2010]GRA-The Minima Game

P3507 [POI2010]GRA-The Minima Game 题目描述 Alice and Bob learned the minima game, which they like very much, recently. The rules of the game are as follows. A certain number of cards lies on a table, each inscribed with a positive integer. The players m

【BZOJ2090/2089】[Poi2010]Monotonicity 2 动态规划+线段树

[BZOJ2090/2089][Poi2010]Monotonicity Description 给出N个正整数a[1..N],再给出K个关系符号(>.<或=)s[1..k].选出一个长度为L的子序列(不要求连续),要求这个子序列的第i项和第i+1项的的大小关系为s[(i-1)mod K+1].求出L的最大值. Input 第一行两个正整数,分别表示N和K (N, K <= 500,000).第二行给出N个正整数,第i个正整数表示a[i] (a[i] <= 10^6).第三行给出K

Codeforces 762A k-th divisor(数论)

题目链接:k-th divisor 直接暴力-- 1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 #define rep(i,a,b) for(int i(a); i <= (b); ++i) 6 #define LL long long 7 8 LL n, k, h, ans; 9 int num; 10 11 int main(){ 12 13 scanf("%lld%lld", &n, &a

bzoj2079[Poi2010]Guilds*

bzoj2079[Poi2010]Guilds 题意: 给一个图染色,要求每个图必须染上某个色同时与另外一个色的点有边相连,问可否满足要求.n≤200000. 题解: 直接上结论:除非有点没有与别的点相连,否则肯定能满足要求. 代码: 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <queue> 5 #define inc(i,j,k) for(int i