zoukankan      html  css  js  c++  java
  • Codeforces 991

    991 F

    题意

    给一个 (le 10^{10}) 的正整数,使用'0'~'9','+','*','^'//乘方字符表示这个数。求表示方法所形成的字符串长度最小的一种。

    Examples

    Input
    2018
    Output
    2018
    Input
    1000000007
    Output
    10^9+7
    Input
    10000000000
    Output
    100^5
    Input
    2000000000
    Output
    2*10^9

    首先,仅用'+','*'不能减小长度。
    其次,乘方的底数必然 (le sqrt{n})
    再次,所有的数最多只能表示为 (a^b*c^d+e^f) 的形式。
    于是,brute force枚举所有情况即可。中间可以用一些小小的优化,如二分。
    复杂度(O(玄学)≈O(sqrt{n}log n))

    Code

    #include<bits/stdc++.h>
    #define INF 1050000000
    using namespace std;
    typedef long long D;
    D n;
    D len(D a){
    	if(!a)return 1;
    	D ret=0;
    	while(a)ret++,a/=10;
    	return ret;
    } 
    struct data{
    	D a,b,c,d,e,f,val,l; //a^b*c^f+d^e
    	data():c(1),d(0),e(1),f(1){}
    	data(D _a,D _b,D _val):a(_a),b(_b),c(1),d(0),e(1),f(1),val(_val){}
    	bool operator <(const data& dat)const{
    		return val==dat.val?l<dat.l:val<dat.val;
    	}
    	void calc(){
    		l=len(a)+len(b)+len(c)+len(d)+len(e)+len(f)+5;
    		if(b==1)l-=2;
    		if(c==1)l-=2;
    		if(d==0)l-=2;
    		if(e==1)l-=2;
    		if(f==1)l-=2;
    	}
    }a[1000000],b[1000000];
    D cnt;
    int main(){
    	cin>>n;
    	a[++cnt]=data(n,1,n);
    	a[cnt].calc();
    	b[cnt]=a[cnt];
    	for(D i=2;i*i<=n;i++){
    		for(D j=i,k=1;j<=n;j*=i,k++){
    			a[++cnt]=data(i,k,j);
    			a[cnt].c=n/a[cnt].val;
    			a[cnt].d=n-a[cnt].val*a[cnt].c;
    			a[cnt].calc();
    			b[cnt]=a[cnt];
    		}
    	}
    	sort(b+1,b+cnt+1);
    	for(D i=1;i<=min(cnt,10000ll);i++){
    		for(D j=1;j<=100;j++){
    			D l=1,r=cnt,mid,ans=-1;
    			while(l<=r){
    				mid=(l+r)>>1;
    				if(a[i].val*j+b[mid].val==n)ans=mid,r=mid-1;
    				else if(a[i].val*j+b[mid].val<n)l=mid+1;
    				else r=mid-1;
    			}
    			if(ans!=-1){
    				a[++cnt]=a[i];
    				a[cnt].c=j;
    				a[cnt].d=b[ans].a;
    				a[cnt].e=b[ans].b;
    				a[cnt].calc();
    			}
    		}
    	}
    	for(D i=1;i<=min(cnt,500000ll);i++){
    		D l=1,r=cnt,mid,ans=-1;
    		while(l<=r){
    			mid=(l+r)>>1;
    			if(a[i].val*b[mid].val<=n)ans=mid,l=mid+1;
    			else r=mid-1;
    		}
    		if(ans!=-1){
    			a[++cnt].a=a[i].a;
    			a[cnt].b=a[i].b;
    			a[cnt].c=b[ans].a;
    			a[cnt].f=b[ans].b;
    			a[cnt].d=n-a[i].val*b[ans].val;
    			a[cnt].calc();
    		}
    	}
    	int minn=INF,mini;
    	for(D i=1;i<=cnt;i++){
    		if(a[i].l<minn){
    			minn=a[i].l;
    			mini=i;
    		}
    	}
    	cout<<a[mini].a;
    	if(a[mini].b!=1)cout<<"^"<<a[mini].b;
    	if(a[mini].c!=1)cout<<"*"<<a[mini].c;
    	if(a[mini].f!=1)cout<<"^"<<a[mini].f;
    	if(a[mini].d!=0)cout<<"+"<<a[mini].d;
    	if(a[mini].e!=1)cout<<"^"<<a[mini].e;
    	return 0;
    }
    
  • 相关阅读:
    JAVA-AbstractQueuedSynchronizer-AQS
    线程封闭
    安全发布对象
    JAVA并发基础
    C#JsonConvert.DeserializeObject反序列化json字符
    Java并发容器
    JAVA简易数据连接池Condition
    Java线程读写锁
    JDK提供的原子类和AbstractQueuedSynchronizer(AQS)
    协方差矩阵分解的物理意义
  • 原文地址:https://www.cnblogs.com/BlogOfchc1234567890/p/10322993.html
Copyright © 2011-2022 走看看