#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
typedef long long LL;
const int N = 30, M = 40000010;
int n,m;
int w[15];
int v[M];
int a[N];
int ans1=0,ans2=0;
void dfs1(int u,int st,int s)
{
if(u>=(n+1)/2)
{
if(st==0 && v[s]>=0) return ;//一个砝码都没有选,且这种状态已经被记录过就返回
v[s] = st;
return ;
}
dfs1(u+1,st,s);//当前砝码不选
dfs1(u+1,st+2*w[u],(s - a[u] + m) % m);//选择一个砝码放到右边
dfs1(u+1,st+w[u],(s + a[u])%m);//选择一个砝码放到左边
}
bool dfs2(int u,int st,int s)
{
if(u>=n)
{
if(v[(m-s+m)%m]>=0)//如果相同的状态存在
{
ans1 = v[(m-s+m)%m];
ans2 = st;
return true;
}
return false;
}
if(dfs2(u+1,st+w[u-(n+1)/2],(s+a[u])%m)) return true;
if(dfs2(u+1,st+2*w[u-(n+1)/2],(s-a[u]+m)%m)) return true;
if(dfs2(u+1,st,s)) return true;
return false;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++) scanf("%d",&a[i]), a[i] %= m;
for(int i=0;i<m;i++) v[i] = -1;
w[0] = 1;
for(int i=1;i<15;i++) w[i] = w[i-1] * 3;
dfs1(0,0,0);//层数,hash值,状态
dfs2((n+1)/2,0,0);
if(ans1 == 0 && ans2 == 0) puts("-1");//不能用if(!dfs2((n+1)/2,0,0))判断有可能找到 ans1 ==0且ans2==0的答案
else
{
int t1=0,t2=0;
int x[N] , y[N];
for(int i=1;i<=(n+1)/2;i++)
{
if((ans1%3)==1) x[t1++] = i;
else if((ans1%3)==2) y[t2++] = i;
ans1/=3;
}
for(int i=(n+1)/2+1;i<=n;i++)
{
if((ans2%3)==1) x[t1++] = i;
else if((ans2%3)==2) y[t2++] = i;
ans2/=3;
}
sort(x,x+t1);
sort(y,y+t2);
printf("%d\n",t1);
for(int i=0;i<t1;i++) printf("%d ",x[i]);
puts("");
printf("%d\n",t2);
for(int i=0;i<t2;i++) printf("%d ",y[i]);
puts("");
}
}
赞一个👏👏