地址:https://zoj.pintia.cn/problem-sets/91827364500/problems/91827369762
思路:二分搜索,对于n行,可从中分开,分别搜索前n/2行和后n/2行,记录其的值以及搜过的点,在对两边结果排序比较即可
Code:
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long LL;
const int MAX_N=15;
const int MAX_S=4105;
int n,m,T;
int a[MAX_N][MAX_N];
vector<LL> d1[MAX_S],d2[MAX_S];
void DFS(int l,int r,vector<LL> d[],int Sum,int p);
int main()
{
ios::sync_with_stdio(false);
cin>>T;
while(T--){
cin>>n>>m;
int s=(1<<n);
for(int i=0;i<s;++i)
d1[i].clear(),d2[i].clear();
for(int i=0;i<n;++i)
for(int j=0;j<n;++j)
cin>>a[i][j];
DFS(0,n/2,d1,0,0);
DFS(n/2,n,d2,0,0);
for(int i=0;i<s;++i)
{
sort(d1[i].begin(),d1[i].end());
sort(d2[i].begin(),d2[i].end());
}
LL aa=0,bb=1;
for(int i=1;i<=n;++i)
bb*=i;
int t,x,r,R;
for(int i=0;i<s;++i)
{
t=s-i-1;
R=d2[t].size(); r=R-1;
for(auto c:d1[i])
{
x=m-c;
while(r>=0&&d2[t][r]>=x){
--r;
}
aa+=R-r-1;
}
}
if(aa){
x=__gcd(aa,bb);
aa/=x; bb/=x;
cout<<bb<<"/"<<aa<<endl;
}else{
cout<<"No solution"<<endl;
}
}
return 0;
}
void DFS(int l,int r,vector<LL> d[],int Sum,int p)
{
if(l==r){
d[p].push_back(Sum);
return;
}
int t=1;
for(int i=0;i<n;t<<=1,++i)
{
if(!(p&t)){
p+=t;
DFS(l+1,r,d,Sum+a[l][i],p);
p-=t;
}
}
}