zoukankan      html  css  js  c++  java
  • Codeforces 986D Perfect Encoding FFT

    题意:

    给定一个数n,选出m个数使得 (Pi_{i=1}^m a_ige n),求(sum_{i=1}^m a_i)的最小值 ,其中(m)的大小不限

    (n)的长度(le 10^6)

    简单的计算可以发现 我们要尽量多的选(3) 在最后特别逼近的时候 会有 (3^x imes2,3^x imes3,3^x imes4)三种选择

    于是我们可以先求出一个逼近(n)的形如(3^x)的数(T),之后暴力枚举三种情况,只要(Tge n)则跳出 否则(T=T*3)继续枚举

    对于一开始求出(T=3^x)的过程 我们可以发(xle log_3 n=len(n)*log_310) 求出(x)后可以通过 (FFT)+快速幂求出(T)

    具体的复杂度不太会分析 我在实现时压了(2)位 看到别人有跑得飞快 开始怀疑是假做法了o(╥﹏╥)o

    #include<bits/stdc++.h>
    using namespace std;
    #define FO(x) {freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);}
    #define pa pair<int,int>
    #define mod 1000000007
    #define ll long long
    #define mk make_pair
    #define pb push_back
    #define fi first
    #define se second
    #define cl(x) memset(x,0,sizeof x)
    #ifdef Devil_Gary
    #define bug(x) cout<<(#x)<<" "<<(x)<<endl
    #define debug(...) fprintf(stderr, __VA_ARGS__)
    #else
    #define bug(x)
    #define debug(...)
    #endif
    const int INF = 0x7fffffff;
    const int N=3e6+5;
    /*
    char *TT,*mo,but[(1<<15)+2];
    #define getchar() ((TT==mo&&(mo=(TT=but)+fread(but,1,1<<15,stdin),TT==mo))?-1:*TT++)//*/
    inline int read(){
        int x=0,rev=0,ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')rev=1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
        return rev?-x:x;
    }
    const int Mod=100;
    int ans,K,ls;
    int M,l,r[N];
    char ss[N];
    
    vector<int>s,g,f;
    const double pi = acos(-1.0);
    struct Cp{
    	double x,y;
    	Cp (double _x=0, double _y=0) {x=_x,y=_y;}
    	Cp operator + (const Cp& rhs) {return Cp(x+rhs.x,y+rhs.y);}
    	Cp operator - (const Cp& rhs) {return Cp(x-rhs.x,y-rhs.y);}
    	Cp operator * (const Cp& rhs) {return Cp(x*rhs.x-y*rhs.y,x*rhs.y+y*rhs.x);}
    }A[N],B[N],x,w,w0;
    inline void FFT(Cp *A,int f) {
    	int i,j,k;
    	for(i=0;i<M;i++) if(i<r[i]) swap(A[i],A[r[i]]);
    	for(i=1;i<M;i<<=1) {
    		w.x=cos(pi/i),w.y=sin(pi/i)*f;
    		for(j=0;j<M;j+=i<<1) {
    			w0.x=1,w0.y=0;
    			for(k=0;k<i;++k) {
    				x=A[j+k];
    				A[j+k]=x+(w0*A[i+j+k]);
    				A[i+j+k]=x-(w0*A[i+j+k]);
    				w0=w0*w;
    			}
    		}
    	}
    	if(f==-1) for(i=0;i<M;++i) A[i].x/=M;
    }
    
    void stretch(vector<int>&a){
    	int p=0,la=a.size();
    	for (int i=0;i<la||p;++i) {
    		if(i>=la) a.pb(0);
    		ll cur=a[i]+p;
    		a[i]=cur%Mod;
    		p=cur/Mod;
    	}
    }
    bool cmp(vector<int>a){
    	int la=a.size(),lb=s.size();
    	if(la<lb) return 0;
    	if(la>lb) return 1;
    	for(int i=la-1;~i;i--) {
    		if(a[i]<s[i]) return 0;
    		if(a[i]>s[i]) return 1;
    	} 
    	return 1;
    }
    bool work(int x){
    	vector<int>h;
    	for(int i=0;i<g.size();i++) h.pb(g[i]*x);
    	stretch(h);
    //	for(int i=0;i<h.size();i++) cout<<h[i]<<" ";cout<<endl; 
    	return cmp(h);
    }
    void solve2(){
    	for(int i=0;i<g.size();i++) g[i]=g[i]*3;
    	stretch(g); 
    }
    //calc 3^n
    vector<int> solve(vector<int>a,vector<int>b){
    	int la=a.size(),lb=b.size();
    //	for(int i=0;i<a.size();i++) cout<<a[i]<<" ";cout<<endl; 
    //	for(int i=0;i<b.size();i++) cout<<b[i]<<" ";cout<<endl; 
    //	bug(la),bug(lb);
    	for(M=1,l=0;M<=la+lb;M<<=1,l++);
    	for(int i=0;i<a.size();i++) A[i].x=a[i],A[i].y=0; 
    	for(int i=0;i<b.size();i++) B[i].x=b[i],B[i].y=0; 
    	for(int i=1;i<M;i++) r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
    	FFT(A,1),FFT(B,1);
    	for(int i=0;i<M;i++) A[i]=A[i]*B[i];
    	FFT(A,-1);
    	vector<int>z(la+lb-1);
    	for(int i=0;i<=la+lb-2;i++) z[i]=(int)(A[i].x+0.5);
    	for(int i=0;i<M;i++) A[i].x=B[i].x=A[i].y=B[i].y=0;
    //	for(int i=0;i<z.size();i++) cout<<z[i]<<" ";cout<<endl; 
    	return z;
    }
    void calc(){
    	f.pb(3),g.pb(1);
    	while(K){
    		if(K&1) g=solve(g,f),stretch(g);
    		K>>=1,f=solve(f,f),stretch(f);
    	}
    }
    int tt[10]={0,1,2,3,4,5,5,6,6,6};
    int main(){
    #ifdef Devil_Gary
    	freopen("in.txt","r",stdin);
    #endif
    	scanf("%s",ss),ls=strlen(ss),reverse(ss,ss+ls);
    	if(ls==1){
    		int zjq=ss[0]-'0'; return cout<<tt[zjq]<<endl,0;
    	}
    	for(int i=0;i<ls;i+=2) {
    		int x=ss[i]-'0';
    		if(i+1<ls) x+=(ss[i+1]-'0')*10;
    //		if(i+2<ls) x+=(ss[i+2]-'0')*100;
    		s.pb(x);
    	}
    	K=(ls-1)*(double)(log(10)/log(3)),--K,ans+=K*3,calc();
    	int ans2=ans;
    //	for(int i=0;i<s.size();i++) cout<<s[i]<<" ";cout<<endl; 
    	for(;;ans+=3,solve2()){
    //		for(int i=0;i<g.size();i++) cout<<g[i]<<" ";bug(ans),cout<<endl; 
    		if(work(2)) {ans+=2;break;}
    		else if(work(3)) {ans+=3;break;}
    		else if(work(4)) {ans+=4;break;}
    	}
    	cout<<ans<<endl;
    }
    
  • 相关阅读:
    手机截屏雷阵雨
    2010年5月20日 用户的数据永远不会靠谱
    2010年5月17日 OCD
    2010年8月9日 流水账
    2010年5月19日 借鉴
    立表为据
    2010年6月2日 回来
    不重视小C打屁屁
    2010年8月16日 知行合一
    2010年5月18日 小细节大隐患
  • 原文地址:https://www.cnblogs.com/devil-gary/p/9115297.html
Copyright © 2011-2022 走看看