[杜教筛] Codechef January Challenge 2018 #SQRGOOD Simplify the Square Root

132人阅读 评论(0) 收藏 举报
分类:

二分转化为μ2的前缀和。
然后转化为O(n13)的运算,但是需要预处理μ的前缀和,大力杜教筛求和。
然后感谢阿爷教我把二分改成了迭代,小范围内一个一个挪,用rho求μ(n),然后就能卡进去了。
复杂度似乎是萎的吧。

#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<vector>
#include<map>
#include<algorithm>
#define pb push_back
using namespace std;
typedef long long ll;

namespace Rho{
  int prime[9]={2,3,5,7,11,13,17,19,23};  
  unsigned long long RR;  
  inline long long R(long long Mo){return (RR+=4179340454199820289ll)%Mo;}  
  inline long long mul(long long x,long long y,long long Mo){  
    long long tmp=(x*y-(long long)((long double)x/Mo*y+0.5)*Mo);  
    return tmp<0?tmp+Mo:tmp;  
  }  
  inline long long Pow(long long x,long long k,long long Mo){  
    long long ans=1;  
    for(;k;k>>=1,x=mul(x,x,Mo))if(k&1)ans=mul(ans,x,Mo);  
    return ans;  
  }  
  inline bool MR(long long n){  
    if(n<=1)return false;  
    for(int i=0;i<9;i++)if(n==prime[i])return true;  
    long long d=n-1;int tmp=0;  
    while((d&1)==0)d>>=1,tmp++;  
    for(int i=0;i<9;i++){  
      long long x=Pow(prime[i],d,n),p=x;  
      for(int j=1;j<=tmp;j++){  
    x=mul(x,x,n);  
    if((x==1)&&(p!=1)&&(p!=n-1))return false;  
    p=x;  
      }  
      if(x!=1)return false;  
    }  
    return true;  
  }  
  inline long long f(long long x,long long c,long long Mo){return (mul(x,x,Mo)+c)%Mo;}  
  inline long long gcd(long long x,long long y){return x==0?y:gcd(y%x,x);}  
  inline long long check(long long c,long long n){  
    long long x=R(n),y=f(x,c,n),p=n;  
    while((x!=y)&&((p==n)||(p==1))){  
      if(x>y)p=gcd(n,x-y);  
      else p=gcd(n,y-x);  
      x=f(x,c,n);y=f(f(y,c,n),c,n);  
    }  
    return p;  
  }

  vector<ll> v;

  inline void rho(long long n){  
    if(n<=1)return;  
    if(MR(n)){v.pb(n);return;}  
    while(true){  
      long long tmp=check(R(n-1)+1,n);  
      if(tmp!=n && tmp!=1){rho(tmp),rho(n/tmp);return;}  
    }  
  }

  inline bool nmu2(ll n){
    v.clear(); rho(n);
    sort(v.begin(),v.end());
    for (int i=0;i<v.size();i++) if (v[i]==v[i+1]) return 1;
    return 0;
  }
}

const int maxn=20000000;
const int N=maxn+5;

int prime[7000000],num;
int mu[N],mu2[N]; 

const int P=10000007;

inline void Pre(int n){
  mu[1]=1; int *vst=mu2;
  for (int i=2;i<=n;i++){
    if (!vst[i]) prime[++num]=i,mu[i]=-1; ll t;
    for (int j=1;j<=num && (t=(ll)i*prime[j])<=n;j++){
      vst[t]=1;
      if (i%prime[j]==0){
    mu[t]=0; break;
      }else
    mu[t]=-mu[i];
    }
  }
  for (int i=1;i<=n;i++) mu2[i]=((bool)mu[i])+mu2[i-1],mu[i]=mu[i-1]+mu[i];
}

map<int,int> Map;  

inline int Sum(int n){  
  if (n<=maxn) return mu[n];  
  if (Map.find(n)!=Map.end()) return Map[n];  
  int tem=1; int l,r;  
  for (l=2;l*l<=n;l++) tem-=Sum(n/l);  
  for (int t=n/l;l<=n;l=r+1,t--){  
    r=n/t;  
    tem-=(r-l+1)*Sum(t);  
  }  
  return Map[n]=tem;  
}

inline ll S(ll n){
  if (n<=maxn) return n-mu2[n];
  int x=sqrt(n); ll ret=0,cur,lst=0;
  for (int i=1,j;i<=x;i=j+1){
    ll t=n/i/i; j=sqrt(n/t);
    ret+=((cur=Sum(j))-lst)*t;
    lst=cur;
  }
  return n-ret;
}

const double PI=acos(-1.0);
const double _K=1.0/(1-6.0/PI/PI);
const double K=2.550546096730430440286486962;

ll n;

inline ll Mod(ll x,ll f){
  if (f>=n){
    while (f>=n){
      f-=Rho::nmu2(x);
      if (f<n) return x;
      x--;
    }
  }else{
    while (f<n){
      f+=Rho::nmu2(x+1);
      if (f>=n) return x+1; 
      x++;
    }
  }
}

int main(){
  freopen("t.in","r",stdin);
  freopen("t.out","w",stdout);
  Pre(maxn);
  scanf("%lld",&(n));
  ll L,R,MID,f1,f2;
  L=1; R=max(1e10,2.550546098*n);
  f1=S(L); f2=S(R);
  while (L+1<R){
    if (f2-n<=1000){
      R=Mod(R,f2);
      break;
    }
    if (n-f1<=1000){
      R=Mod(L,f1);
      break;
    }
    MID=L+(long double)(n-f1)/(f2-f1)*(R-L);
    ll f=S(MID);
    if (f==n){
      R=Mod(MID,f); break;
    }
    if (f>n)
      f2=f,R=MID;
    else
      f1=f,L=MID;
  }
  printf("%lld\n",R);
  return 0;
}
查看评论

[ 杜教筛 数论 ] Codechef January Challenge 2018 #SQRGOOD

题目大意 给你一个数 n(n≤1018)n(n\le 10^{18}) ,求第 nn 个含大于 11 平方因子的数。 比赛时卡常卡到头秃 发现一个数 xx 含有平方因子等价于 μ2x=0\mu_...
  • gjghfd
  • gjghfd
  • 2018-01-23 11:24:04
  • 49

[整体二分] Codechef January Challenge 2018 #MONSTER Killing Monsters

整体二分,然后问题变成,子集加,单点查询,然后像CTSC吉夫特 可以用经典的二进制分高位低位的搞搞。调个参,大概是高5位低12位。 不知道在线怎么做。 #include #include #i...
  • u014609452
  • u014609452
  • 2018-01-19 14:11:46
  • 197

bzoj 3944: Sum 杜教筛

本来以为这种东西只能O(N)线性筛,但是大千世界,无(sang)奇(xin)不(bing)有(kuang),确实存在更快的算法。        省选的时候rzz讲这种东西在国内OI称为杜教筛,用来求数...
  • lych_cys
  • lych_cys
  • 2016-03-24 20:45:40
  • 5518

[Notes] 杜教筛学习笔记

作为蒟蒻的我很羞耻的不会杜教筛 于是我开始学 可以发现 blog已经被数论函数和杜教筛刷屏了 杜教筛的学习要点by糖老师 传送门 吉丽: http://jiruyi91...
  • u014609452
  • u014609452
  • 2017-01-26 23:34:52
  • 2625

杜教筛 学习小结

今年的GDKOI居然考了反演,还要用杜教筛,狠狠的把我骇了一条, 回来在51nod上随便点开几题看起啦像是反演的题,发现都是要用杜教筛(这RP~), 好吧好吧,那就学杜教筛咯~杜教筛的套路有几个大...
  • HOWARLI
  • HOWARLI
  • 2017-03-13 12:54:39
  • 981

杜教筛

莫比乌斯函数前缀和 51nod - 1244 令S(n)=∑ni=1μ(i)S(n)=\sum_{i=1}^n\mu(i),求S(n),1≤n≤1010S(n),1 \le n \le 10^{1...
  • outer_form
  • outer_form
  • 2017-07-15 17:22:04
  • 702

PE 439 【莫比乌斯反演】【杜教筛】

垃圾题,坑了我一天QAQ题目大意:求∑Ni=1∑Nj=1σ(ij)\sum_{i=1}^N\sum_{j=1}^N\sigma(ij),N=1011N = 10^{11}∑Ni=1∑Nj=1σ(ij)...
  • beginendzrq
  • beginendzrq
  • 2016-04-18 14:45:51
  • 1839

[杜教筛 约数和前缀和] 51Nod 1220 约数之和

吉丽博客传送门:http://jiruyi910387714.is-programmer.com/posts/195270.html 套用公式后反演 然后杜教筛求和 比较有意思的是其间我算...
  • u014609452
  • u014609452
  • 2017-01-26 23:01:19
  • 939

[杜教筛 约数个数前缀和] BZOJ 4176 Lucas的数论

吉丽博客传送门:http://jiruyi910387714.is-programmer.com/posts/195270.html 套用陈老师r老师等式后反演 #include #inc...
  • u014609452
  • u014609452
  • 2017-01-26 22:54:41
  • 799

BZOJ_P3944 Sum(数论+杜教筛)

BZOJ传送门Time Limit: 10 Sec Memory Limit: 128 MB Submit: 1108 Solved: 270 [Submit][Status][Discuss...
  • qq_18455665
  • qq_18455665
  • 2016-03-25 20:52:17
  • 739
    个人资料
    持之以恒
    等级:
    访问量: 40万+
    积分: 1万+
    排名: 1233
    文章分类
    最新评论