zoukankan      html  css  js  c++  java
  • Codeforces 986D Perfect Encoding FFT 分治 高精度

    原文链接https://www.cnblogs.com/zhouzhendong/p/9161557.html

    题目传送门 - Codeforces 986D

    题意

      给定一个数 $n(nleq 10^{1500000})$ , 求满足 $(prod b_i)geq n$ 的 $min(sum b_i)$ 。

    题解

      这题是下面链接中那题的加强版。

      BZOJ1263 [SCOI2006]整数划分 高精度

      这题的做法是预估出大概有多少个 $3$ ,然后最后几个数一个一个加上去就可以了。

      至于求 $3$ 的快速幂,要用FFT优化。

      时间复杂度:

    $$T(m)=T(m/2)+mlog m=mlog m$$

      其中这里的 $m$ 与输入的 $n$ 的位数同阶。

      注意点:

      1.  本题卡常,要压位,我压了3位,但是2位好像也可以过。

      2.  注意一下 $n=1$ 的情况。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int N=(1<<21)+1;
    const double PI=acos(-1.0);
    int m;
    char s[N];
    int bit=1000;
    struct Big{
    	int len;
    	LL a[N];
    	void clear(){
    		len=0;
    		memset(a,0,sizeof a);
    	}
    	void print(){
    		for (int i=len;i>=1;i--)
    			printf("%03d",(int)a[i]);
    		puts("");
    	}
    	bool operator >= (Big &x){
    		if (len!=x.len)
    			return len>x.len;
    		for (int i=len;i>=1;i--)
    			if (a[i]!=x.a[i])
    				return a[i]>x.a[i];
    		return 1;
    	}
    	void pushbits(){
    		for (int i=1;i<=len;i++)
    			a[i+1]+=a[i]/bit,a[i]%=bit;
    		while (a[len+1]){
    			len++;
    			a[len+1]=a[len]/bit;
    			a[len]%=bit;
    		}
    	}
    	void operator *= (int x){
    		for (int i=1;i<=len;i++)
    			a[i]*=x;
    		pushbits();
    	}
    }n,x,tmp;
    struct C{
    	double r,i;
    	C(){}
    	C(double _r,double _i){r=_r,i=_i;}
    	C operator + (C x){return C(r+x.r,i+x.i);}
    	C operator - (C x){return C(r-x.r,i-x.i);}
    	C operator * (C x){return C(r*x.r-i*x.i,r*x.i+i*x.r);}
    }A[N],B[N],w[N];
    int R[N];
    void FFT(C a[],int n){
    	for (int i=0;i<n;i++)
    		if (R[i]>i)
    			swap(a[i],a[R[i]]);
    	for (int t=n>>1,d=1;d<n;d<<=1,t>>=1)
    		for (int i=0;i<n;i+=(d<<1))
    			for (int j=0;j<d;j++){
    				C tmp=w[t*j]*a[i+j+d];
    				a[i+j+d]=a[i+j]-tmp;
    				a[i+j]=a[i+j]+tmp;
    			}
    }
    void Times (Big &a,Big &b,Big &c){
    	int n,d;
    	for (n=1,d=0;n<a.len+b.len;n<<=1,d++);
    	for (int i=0;i<n;i++){
    		R[i]=(R[i>>1]>>1)|((i&1)<<(d-1));
    		w[i]=C(cos(PI*2*i/n),sin(PI*2*i/n));
    		A[i]=B[i]=C(0,0);
    	}
    	for (int i=1;i<=a.len;i++)
    		A[i-1].r=a.a[i];
    	for (int i=1;i<=b.len;i++)
    		B[i-1].r=b.a[i];
    	FFT(A,n),FFT(B,n);
    	for (int i=0;i<n;i++)
    		A[i]=A[i]*B[i],w[i].i*=-1.0;
    	FFT(A,n);
    	c.clear();
    	for (int i=0;i<n;i++)
    		c.a[i+1]=(LL)(A[i].r/n+0.5);
    	c.len=n;
    	while (c.a[c.len]==0&&c.len>1)
    		c.len--;
    	c.pushbits();
    }
    void Pow(int y){
    	if (y==0){
    		x.clear();
    		x.a[x.len=1]=1;
    		return;
    	}
    	Pow(y/2);
    	Times(x,x,x);
    	if (y&1)
    		x*=3;
    }
    bool check(Big &x,int y){
    	tmp=x;
    	tmp*=y;
    	return tmp>=n;
    }
    int main(){
    	scanf("%s",s+1);
    	n.len=strlen(s+1);
    	int pw10[3]={1,10,100};
    	for (int i=1;i<=n.len;i++)
    		n.a[(n.len-i+1-1)/3+1]+=pw10[(n.len-i)%3]*(s[i]-'0');
    	m=max(0,(int)(n.len*log(10)/log(3))-3);
    	n.len=(n.len-1)/3+1;
    	if (n.len==1&&n.a[1]==1){
    		puts("1");
    		return 0;
    	}
    	Pow(m);
    	while (1){
    		for (int i=2;i<=4;i++)
    			if (check(x,i)){
    				printf("%d",m*3+i);
    				return 0;
    			}
    		x*=3;
    		m++;
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    并查集
    强联通分量,缩点
    最短路径
    最小生成树
    拓扑排序
    图的遍历
    图论基础知识
    数据库四种隔离级别
    MySQL 索引 乐观锁 悲观锁
    MYSQL+正则
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/CF986D.html
Copyright © 2011-2022 走看看