Codeforces 986D Perfect Encoding FFT

题意:

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

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

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

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

对于一开始求出\(T=3^x\)的过程 我们可以发\(x\le 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;
}
posted @ 2018-05-31 10:39  Devil_Gary  阅读(705)  评论(3编辑  收藏  举报