2018ICPC青岛站 D . Magic Multiplication(构造 模拟)

linkkk

题意:

定义一个新运算为两个数A,B上每一位相乘,然后顺次接在一起,现在给定结果C和原来两个数字的长度,要求恢复成原来的数字A,B
若有多解输出A字典序最小的,A相同输出B字典序最小的,无解输出Impossible

思路:

枚举 A A A的第一位数字,这样可以求出 B B B,再用 B B B去求 A A A剩下的数字,同时检查是否合法。
有个问题就是两个一位数相乘会得到一位数或两位数,如果判断是用 C C C的几位来求呢。
如果说当前满足的式子是 z = ( x ∗ y ) m o d    10 z=(x*y)\mod10 z=(xy)mod10,已知 x , z x,z x,z,那么如果 x > = z x>=z x>=z的话, z z z就是一位数;否则, z z z是两位数。但是如果 z = = 0 z==0 z==0的时候也是一位数。
然后模拟就好了,细节比较多。

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;typedef unsigned long long ull;
typedef pair<ll,ll>PLL;typedef pair<int,int>PII;typedef pair<double,double>PDD;
#define I_int ll
inline ll read(){ll x=0,f=1;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;}
#define read read()
#define rep(i, a, b) for(int i=(a);i<=(b);++i)
#define dep(i, a, b) for(int i=(a);i>=(b);--i)
ll ksm(ll a,ll b,ll p){ll res=1;while(b){if(b&1)res=res*a%p;a=a*a%p;b>>=1;}return res;}
const int maxn=4e5+7,maxm=1e6+7,mod=1e9+7;

int n,m,pos=0,len;
int a[maxn],b[maxn],c[maxn];
int pa=0,pb=0,pc=0;
int ans_a[maxn],ans_b[maxn];

int getb(int x){//a[1]=x
    pb=0;
    int idx=0;
    while(pos<len&&idx<m){
        int now=c[pos];
        if(now>=x){
            if(now%x) return 0;
            b[idx]=now/x;
            idx++;
        }
        else{
            if(pos==len-1&&now!=0) return -100;
            if(now!=0) now=now*10+c[++pos];
            if(now%x) return 0;
            b[idx]=now/x;
            idx++;
        }
        pos++;
    }
    pb=idx;
  //  cout<<idx<<" "<<m<<" "<<pos<<" "<<len<<endl;
    if(idx==m) return 1;
    return 0;
}

int geta(int x){
	pa=1;
	a[0]=x;
    int bf=b[0];
	while(pos<len&&pa<n){
		int now=c[pos];
		int ta=0;
		if(now>=bf){
			if(now%bf) return 0;
			a[pa]=now/bf;
			ta=now/bf;
			pa++;
		}
		else{
			if(pos+1==len&&now!=0) return 0;
			if(now!=0) now=now*10+c[++pos];
			if(now%bf) return 0;
			a[pa]=now/bf;
			ta=now/bf;
			pa++;
		}
		pos++;
		for(int i=1;i<m;i++){
			int tb=b[i];
			int num=ta*tb;
			int now=c[pos];
			if(num>=10){
				if(pos==len-1) return 0; 
				now=now*10+(c[++pos]);
				if(num!=now) return 0;
			}
			else{
				if(num!=now) return 0;
			}
			pos++;
		}
	}
	//cout<<pos<<"**"<<len<<endl;
	if(pa!=n||pos!=len) return -5;
	return 1;
}


int main(){
    int _=read;
    while(_--){
        n=read,m=read;
        string s;cin>>s;
        len=s.size();
        pos=0;
        for(int i=0;i<len;i++){
        	c[i]=s[i]-'0';
        }
        pa=pb=pc=0;
        
        bool flag=0;
        for(int i=1;i<=9;i++){
        	pos=0;
        	int ff=getb(i);
            /*if(i==1){
            	cout<<ff<<endl;
            	for(int i=0;i<m;i++) cout<<b[i];
            	puts("");
            }*/
            if(ff==1){
                int f=geta(i);
                /*if(i==1){
                	cout<<f<<endl;
                	for(int i=0;i<n;i++) cout<<a[i];
            		puts("");
                }*/
                if(f==1){
                 
                    for(int i=0;i<n;i++) ans_a[i]=a[i];
                    for(int i=0;i<m;i++) ans_b[i]=b[i];
                    
                    flag=1;
                    break;
                }
            }
        }
       // cout<<flag<<endl;
        if(flag){
        	rep(i,0,n-1) printf("%d",ans_a[i]);
        	printf(" ");
        	rep(i,0,m-1) printf("%d",ans_b[i]);
        	puts("");
        }
        else puts("Impossible");
    }
    return 0;
}
/*
1
2 2
8101215
*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

豆沙睡不醒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值