2021年度训练联盟热身训练赛第一场 C.New Math

题目链接
2021年度训练联盟热身训练赛第一场 C.New Math_第1张图片
2021年度训练联盟热身训练赛第一场 C.New Math_第2张图片
2021年度训练联盟热身训练赛第一场 C.New Math_第3张图片
2021年度训练联盟热身训练赛第一场 C.New Math_第4张图片
题目大意: 定义一种不进位乘法和加法,给出n让你求出a使得a*a=n
先看定义的不进位的乘法和加法。

2021年度训练联盟热身训练赛第一场 C.New Math_第5张图片
看下这个图理解一下,就是每一位的乘法不进位,然后每一位的加法也不进位。
通过 a ∗ a = n a*a=n aa=n我们其实可以知道如果 a a a的位数为 x x x那么 n n n的位数应该是 2 ∗ x − 1 = m 2*x-1=m 2x1=m m m m n n n的位数。所以我们可以通过 n n n的位数得到 a a a的位数,也可以通过是否是奇数判断是否可能有解。
我们可以通过固定的位数来判断对应的结果对应的位数。(从后从前都一样)
先从后看,好理解点。
还用上面的例子:1234如果我们确定后两位34那么我们就可以直接算出最终结果的后两位。因为前两位对结果的后两位不做贡献。我们就可以每次判断一下。看看当前位是否可以填上对应的数,可以我们再继续往前填。最后一定要全体判断一下就是判 n n n的位数是否全部对应。这样不一定保证结果最小。
如果我们从前往后填充就可以得到最小值。

#include 
#include 
#include 
#include
#include
#include
#include 
#include 
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
typedef pair<ll,ll> pii;
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define mem(a,x) memset(a,x,sizeof(a))
#define debug(x) cout << #x << ": " << x << endl;
#define rep(i,n) for(int i=0;i<(n);++i)
#define repi(i,a,b) for(int i=int(a);i<=(b);++i)
#define repr(i,b,a) for(int i=int(b);i>=(a);--i)
const int maxn=2e6+10;
#define inf 0x3f3f3f3f
#define sf scanf
#define pf printf
const int mod=10000;
const int MOD=1e9+7;

inline int read() {
     
    int x=0;
    bool t=false;
    char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    if(ch=='-')t=true,ch=getchar();
    while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    return t?-x:x;
}

vector<ll> m1;
vector<ll> m2;
priority_queue<ll, vector<ll>, greater<ll> > mn;  //上  小根堆 		小到大
priority_queue<ll, vector<ll>, less<ll> > mx;  //下   	大根堆  	大到小
map<ll,ll>mp;
ll n,m,p;
ll ans=1e18;
ll dis[maxn],vis[maxn];
ll a[maxn],b[maxn],c[maxn];
ll cnt,flag;
bool check(ll num) {
     
    for(int i=0; i<=60; i++) c[i]=0;
    for(int i=1; i<=num; i++) {
     
        for(int j=1; j<=num; j++) {
     
            c[i+j-1]=(c[i+j-1]+b[i]*b[j])%10;
        }
    }
    for(int i=1; i<=num; i++) {
     
        if(c[i]!=a[i]) return 0;
    }
    return 1;
}
void dfs(ll num) {
     
    if(num==n+1) {
     
        if(check(n+n-1)) {
     
                ll p=0;
            for(int i=n; i>=1; i--) {
     
                p=p*10+b[i];
            }
            ans=min(ans,p);
            flag=1;
        }
        return ;
    }
    for(int i=0; i<=9; i++) {
      ///数字
        if(num==n&&i==0) continue;
        b[num]=i;
        if(check(num)) {
     
            dfs(num+1);
        }
        b[num]=0;
    }
}
int main() {
     
    string str;
    cin>>str;
    ll len=str.size();

    if((len+1)%2==1) puts("-1");
    else {
     
        for(int i=len,j=0; i>=1; i--,j++) {
     
            a[i]=str[j]-'0';
        }
        n=(len+1)/2;///数位
        dfs(1); 
        if(!flag) puts("-1");
        else printf("%lld\n",ans);
    }
    return 0;
}


你可能感兴趣的:(思维,数论)