题目:
分析:这里给的搜素题,总觉得不是很好。
终于遇到一道还不错的。
本以为是基础。
0优化代码:
#include
using namespace std;
long long A[50];
int m;
long long n;
long long ans=0;
void f(long long rest,int num)
{
if(num==n) { ans++; return; }
if(rest<A[num])
{
ans++;
return;
}
f(rest,num+1);
f(rest-A[num],num+1);
}
int main()
{
cin>>m>>n;
for(int i=0;i<m;i++) cin>>A[i];
sort(A,A+m);
f(n,0);
cout<<ans;
}
相同的应该是可以优化的:
引入一个c—组合数,相同的可以极大的节省
代码:
#include
using namespace std;
int m;
long long n;
long long ans=0;
long long cc[41][41];
map<long long,int> mm;
vector<long long> v;
void fc()
{
for(int i=0;i<41;i++) cc[i][0]=1;
for(int i=1;i<41;i++)
for(int j=1;j<=i;j++) cc[i][j]=cc[i][j-1]*(i-j+1)/j;
}
void f(long long rest,int num,long long b)
{
if(num==v.size()) { ans+=b; return; }
if(rest<v[num])
{
ans+=b;
return;
}
f(rest,num+1,b);
for(int i=1;i<=mm[v[num]];i++)
{
if(i*v[num]<=rest)
{
f(rest-i*v[num],num+1,b*cc[mm[v[num]]][i]);
}
else break;
}
}
int main()
{
fc();
cin>>m>>n;
for(int i=0;i<m;i++)
{
long long c;
cin>>c;
if(mm[c]!=0) { mm[c]++; continue; }
mm[c]++;
v.push_back(c);
}
sort(v.begin(),v.end());
f(n,0,1);
cout<<ans;
}
竟然只通过了40。
看来我小看了省选/NOI-的难度。
看题解:
折半搜索:
我也没理解为什么能降低的比我的还多。
代码:很容易理解,就是分成两部分,用一个数组记录所有可能的搜索结果。然后用stl的搜索函数进行合并。
代码:
#include
using namespace std;
long long A[50];
int m;
long long n;
long long ans=0;
long long suma[1<<21],sumb[1<<21];
void f1(long long sum,int l,int r,long long & cnt)
{
if(sum>n) return;
if(l>r)
{
suma[cnt]=sum;
cnt++;
return;
}
f1(sum+A[l],l+1,r,cnt);
f1(sum,l+1,r,cnt);
}
void f2(long long sum,int l,int r,long long & cnt)
{
if(sum>n) return;
if(l>r)
{
sumb[cnt]=sum;
cnt++;
return;
}
f2(sum+A[l],l+1,r,cnt);
f2(sum,l+1,r,cnt);
}
int main()
{
cin>>m>>n;
for(int i=0;i<m;i++) cin>>A[i];
long long cnta=0;
long long cntb=0;
f1(0,0,m>>1,cnta);
f2(0,(m>>1)+1,m-1,cntb);
sort(suma,suma+cnta);