1. 程式人生 > >2016年第七屆 藍橋杯 全國總決賽B題(完全平方數)

2016年第七屆 藍橋杯 全國總決賽B題(完全平方數)

題目意思就是:
給你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; }