2016年第七屆 藍橋杯 全國總決賽B題(完全平方數)
阿新 • • 發佈:2019-02-09
題目意思就是:
給你0,1,2,3,4,5,6,7,8,9十個數字,要你選出任意一個或幾個組合在一起成為完全平方數,每個數字都必須選且只能選一次,求可能的方案。
比如有其中幾種符合題意的情況:
0 16 25 73984
0 1 625 73984
0 4 16 537289
0 16 784 5329
0 25 784 1936
ans=300;
#include<iostream>
using namespace std;
#include<cstring>
#include<cstdio>
#include<vector>
#include<algorithm>
#include<cmath>
typedef long long ll;
const ll inf=(ll)(0x3f3f3f3f);
int ans=0;
ll t[105];
vector<ll> vec[500];
int len=0;
ll b[15];
int lens[600];
const int maxn=900005;
ll pri[maxn];
bool judge(ll x) {
ll o1=(ll)(sqrt(x));
return o1*o1==x;
}
void solve(ll *a,int num) {
memset(b,inf,sizeof (b));
int u=0,pos=0;
bool is=true;
for(int i=0; i<num; ++i) {
ll s=0;
if(!a[pos]&&t[i]>1) {
is=false;
break;
}
for(int j=pos; j<t[i]+pos; ++j) {
s=s*10+a[j];
}
b[u]=s;
++u;
pos=t[i]+pos;
}
if (is) {
sort(b,b+u);
bool issame=true;
for(int i=0; i<len; ++i) {
int sj=lens[i];
if(sj!=u)continue;
bool same1=true;
for(int j=sj-1; j>=0; --j) {
if(vec[i][j]!=b[j]) {
same1=false;
break;
}
}
if(same1) {
issame=false;
break;
}
}//判重
if(issame) {
++len;
lens[len-1]=u;
for(int i=0; i<u; ++i) {
vec[len-1].push_back(b[i]);
// cout<<b[i]<<" ";
}
// cout<<endl;
++ans;
}
}
}
ll ppp=(ll)maxn;
void dfs(ll *a,int sum,int num,int pos) {
if(!sum) {
solve(a,num);
} else if(sum<0);
else {
for(int i=sum; i>=1; --i) {//求劃分數
t[num]=i;
ll ts=0;
bool can=true;
if(i>1&&a[pos]==0)continue;
for(int j=pos; j<pos+i&&can; ++j) {
ts=ts*10+a[j];
}
if((ts<ppp&&(!pri[ts]))||!judge(ts))continue;//剪枝
dfs(a,sum-i,num+1,pos+i);
}
}
}
int main() {
ll a[]= {0,1,2,3,4,5,6,7,8,9};
for(int i=0; i<500; ++i)
vec[i].clear();
for(ll i=0; i<ppp; ++i) {
pri[i]=judge(i);
}
int op=0;
do {
dfs(a,10,0,0);
} while(next_permutation(a,a+10));
cout<<ans<<endl;
return 0;
}