New Maths
题意:
定义一个不进位的乘法运算 ⊗,先给出一个n,判断是否存在a,满足a ⊗ a = n
n的长度最多是25
题解:
17 * 17正常等于289
17 ⊗ 17 =149
如果a的长度为x,那么最后得到的n的长度len是2x-1
倒着推就是:(len+1)>>1
n的位数小于等于25,所以a的位数一定小于等于13,直接暴力枚举,然后判断合理性
判断依据:
逐位用 O(n) 求卷积某一位的方法求出 a ⊗ a 每一位的结果,并与 n 对应位进行比较。
可以发现每一位的值,都是交叉相乘相加后取余,如果第3位,就是1×3,2×2,1×3(这里的1,2,3表示下标)。
至于为什么是交叉相乘相加得到?
额。。等我搞清为什么再更新
0427
突然想起这个题
参考文章
我们可以从前往后依次填充数字,然后对填的数字进行运算,判断是否能完全对应,因为是从前往后填,所以答案一定是最小值
代码:
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <string.h>
#include <vector>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <utility>
#define pi 3.1415926535898
#define ll long long
#define lson rt<<1
#define rson rt<<1|1
#define eps 1e-6
#define ms(a,b) memset(a,b,sizeof(a))
#define legal(a,b) a&b
#define print1 printf("111\n")
#define pb(x) push_back(x)
using namespace std;
const int maxn = 2e5+10;
const int inf = 0x1f1f1f1f;
const ll llinf =1e17+10;
const ll mod = 1e9+7;int n,len;
char s[maxn];
int a[maxn];
int b[maxn];
ll ans;bool check(int k)
{int res=0;for(int i=1; i<=k; i++)res=(res+b[i]*b[k-i+1])%10;return res==a[k];
}void get_max()
{for(int i=len+1; i<=n; i++)//判断当前数字是否与N相同{if(!check(i))return;}ll tem=0;for(int i=len; i>=1; i--)tem=tem*10+b[i];ans=min(tem,ans);
}void dfs(int x)
{if(x>len)//超过长度时 判断是否满足后面半段{get_max();return;}for(int i=0; i<=9; i++)//枚举该位置上的数字{b[x]=i;if(check(x))//剪枝 将该位置填入i后 判断此时得到的Bx是否和Nx相同 {dfs(x+1);}}}int main()
{scanf("%s",s+1);len=strlen(s+1);ans=1e18;if(len%2==0)printf("-1\n");else{n=len;for(int i=1; i<=n; i++)a[n-i+1]=s[i]-'0';len=(len+1)/2;dfs(1);//从1开始枚举位置printf("%lld\n",(ans==1e18)?-1:ans);}system("pause");return 0;
}
#include <map>
#include <queue>
#include <string>
#include<iostream>
#include<stdio.h>
#include<string.h>
#include <algorithm>
#include <math.h>
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;
}