[bzoj3957][構造]To Add or to Multiply

Description

工業計算機處理器公司爲顧客量身定做了非常快速、用於專門目的的處理單元。a-C-m系列的處理器(比如1-C-2和5-C-3)的指令集只有兩種操作:
  • A 數值加a   • M 數值乘m
  處理器接收一個整數,執行一個A和M的指令序列(即程序)來修改輸入,然後輸出結果。舉個例子,1-C-2處理器執行程序AAAM處理輸入2返回輸出10(計算過程是2→3→4→5→10),然而5-C-3處理器用相同的程序和輸入返回51(2→7→12→17→51)。
  你是一個被指定做一個頂級祕密項目的a-C-m程序員。這意味着你不會被告知你的程序執行的精確輸入。但會得到四個特別的值p,q,r,s,以及下列條件
  1、輸入保證是一個在p、q之間的數   2、輸出必須是一個在r,s之間的數。
  給你一個a-C-m處理器和p,q,r,s這四個數。你的工作是構想最短的a-C-m程序,使得任意任意x保證p≤x≤q,返回一個輸出y使得r≤y≤s。如果有多個最短的程序,選擇字典序最小的,而一個程序即是由A和M組成的字符串。

Input

輸入包含多組數據。每組數據在一行中給你6個整數a,m,p,q,r,s,每個就像上面描述的一樣。 末行輸入6個0作爲結束。

Output

對於每組數據,在你的程序前輸出數據的編號,程序即像上面描述的一樣。輸出單詞“empty”,如果最好的程序沒有操作。輸出單詞“impossible”如果沒有程序滿足具體要求。
輸出一個用空格分隔的字符串序列,任兩個相鄰的字符串形式分別爲“nA”和“nM”,n>0。前者表示n個連續的操作A,後者表示n個連續的操作M。

Sample Input

1 2 2 3 10 20

1 3 2 3 22 33

3 2 2 3 4 5

5 3 2 3 2 3

0 0 0 0 0 0

Sample Output

Case 1: 1A 2M

Case 2: 1M 2A 1M

Case 3: impossible

Case 4: empty

HINT

所有的的a,m,p,q,r,s∈[1,1000000000],且p≤q,r≤s。

題解

感覺我已經變得奇奇妙妙了…
菜的真實
首先你可以知道,對於任意輸入一個數xx,最終一定可以變爲這樣的形式
xmk+a(tkmk+tk1mk1...+t0m0)x*m^k+a*(t_k*m^k+t_{k-1}*m^{k-1}...+t_0*m^0)
主要是我沒有把這個形式後面寫成係數允許爲0的形式然後就掛了
你可以發現,在mm不等於11的情況下這個kk最多隻有3030,然而m=1m=1的情況下只會用加aa的情況,這個判掉就可以了…
所以枚舉一下這個kk,我們只需要讓x=px=p時滿足上式大於等於rrx=qx=q時上式小於等於ss即可
我們可以得到他們的差分別是s1s1s2s2,不妨設後面的式子爲p1p1p2p2
我們發現p1,p2p1,p2均是由aa組成的,所以可以把s1=s1as1=\lceil\frac{s1}{a}\rceils2=s2as2=\lfloor\frac{s2}{a}\rfloor,然後構造後面的多項式
發現其實這是一個mm進制的數,我們把s1,s2s1,s2寫成mm進制,類似數位dp一下就可以了…
大概就是如果前面不頂兩個界,直接填0就可以了
如果頂着下界,看看這個位能不能填一個大於下界的數,讓後面的位置全部填0
否則的話按下界填就可以了
OZY天下第一!!!!!!!!!!!

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<ctime>
#include<map>
#include<bitset>
#include<set>
#define LL long long
#define mp(x,y) make_pair(x,y)
#define pll pair<long long,long long>
#define pii pair<int,int>
using namespace std;
inline int read()
{
	int f=1,x=0;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
int stack[20];
inline void write(LL x)
{
	if(x<0){putchar('-');x=-x;}
    if(!x){putchar('0');return;}
    int top=0;
    while(x)stack[++top]=x%10,x/=10;
    while(top)putchar(stack[top--]+'0');
}
inline void pr1(int x){write(x);putchar(' ');}
inline void pr2(LL x){write(x);putchar('\n');}
int a,m,p,q,r,s;
int sum;
int temp[2][35],ln[2],ans[35],lin[35];
void get(int x,int len,int opt)
{
	memset(temp[opt],0,sizeof(temp[opt]));
	LL base=1;ln[opt]=0;
	for(int i=1;i<=len;i++)
	{
		temp[opt][++ln[opt]]=x%m;
		if(i==len)temp[opt][i]=x;
		x/=m;
		if(!x)return ;
	}
}

int num1[110],num2[110],ln1;
int as1[110],as2[110],ln2;
void work(int mx)
{
	ln1=0;memset(num1,0,sizeof(num1));
	for(int i=1;i<=mx;i++)
	{
		if(lin[i])
		{
			num1[++ln1]=lin[i];num2[ln1]=1;
		//	if(i!=mx)
			ln1++;
		}
		if(!ln1)ln1=1;
		if(i!=mx)num1[ln1]++,num2[ln1]=2;
	}
	if(lin[mx])ln1--;
}
int main()
{
//	freopen("a.in","r",stdin);
//	freopen("a.out","w",stdout);
	int tt=0;
	while(++tt)
	{
		memset(num2,0,sizeof(num2));
		memset(as1,0,sizeof(as1));memset(as2,0,sizeof(as2));
		a=read();m=read();p=read();q=read();r=read();s=read();
		if(!a&&!m&&!p&&!q&&!r&&!s)break;
		printf("Case %d: ",tt);
		if(p>=r&&q<=s)puts("empty");
		else if(q>s)puts("impossible");
		else
		{
			if(m==1)
			{
				int down=(r-p)/a;if((r-p)%a)down++;
				int up=(s-q)/a;if((s-q)%a)up++;
				if(p+1LL*down*a>s||q+1LL*up*a>s||down>up)puts("impossible");
				else printf("%dA\n",down);
			}
			else
			{
				bool tf=false;sum=(1<<31-1);
				LL base=1;int del=a;a=1;
				for(int i=0;i<=30;i++)
				{
					memset(lin,0,sizeof(lin));
					if(i)base=base*m;
					if(base>s||1LL*p*base>s||1LL*q*base>s)break;
					int s1=r-p*base,s2=s-q*base;
					if(s1<0)s1=0;
					s1=(s1+del-1)/del;s2=s2/del;
					get(s1,i+1,0);get(s2,i+1,1);
					int tot=i,gg=0;bool yes=0,ok=1;
					for(int j=max(ln[0],ln[1]);j>=1;j--)
					{
						if(!gg)//前面填的都是頂下界的 
						{
							if(a*((temp[0][j]+a-1)/a)>temp[1][j]){ok=0;break;}
							int num=a*((temp[0][j]+a-1)/a);
							if(num>temp[0][j])tot+=num/a,lin[j]=num/a,gg=1;
							else
							{
								if(num+a<=temp[1][j]||yes)
								{
									bool bk=false;
									for(int k=j-1;k>=1;k--)if(temp[0][k]){bk=true;break;}
									if(bk)tot+=num/a+1,lin[j]=num/a+1,gg=1;
									else tot+=num/a,lin[j]=num/a;
								}
								else tot+=num/a,lin[j]=num/a;
							}
						}
						else lin[j]=0;
						if(temp[0][j]<temp[1][j])yes=1;
					}
					if(!ok)continue;
					tf=1;work(i+1);
					if(tot<sum)
					{
						sum=tot;
						memcpy(as1,num1,sizeof(as1));memcpy(as2,num2,sizeof(as2));
						ln2=ln1;
					}
					else if(tot==sum)
					{
						bool ok=true;
						for(int i=ln1,j=ln2;i>=1,j>=1;i--,j--)
						{
							if(num2[i]>as2[j]){ok=false;break;}
							if(num2[i]<as2[j])break;
							if(num1[i]==as1[j])continue;
							else
							{
								if(num1[i]>as1[j])
								{
									if(num2[i]>as2[j-1]){ok=false;break;}
									else break;
								}
								else
								{
									if(as2[j]>num2[i-1]){ok=false;break;}
									else break;
								}
							}
						}
						if(ok)
						{	
							memcpy(as1,num1,sizeof(as1));memcpy(as2,num2,sizeof(as2));
							ln2=ln1;
						}
					}
				}
				if(!tf)puts("impossible");
				else
				{
					for(int i=ln2;i>=1;i--)
					{
						printf("%d",as1[i]);
						if(as2[i]==1)putchar('A');
						else putchar('M');
						if(i!=1)putchar(' ');
					}
					puts("");
				}
			}
		}
	}
	return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章