更新後的代碼:
今天重新做這道題的時候想了很多種思路
最後終於想出了自認爲完美的思路,結果卻超時
真的是感覺自己沒救了
最後加了記憶化搜索,AC了
好了先說下思路吧,不知道大家住沒注意m<=10
我們可以把大部分的數據寫成成對的形式例如n=27 m=6的這組數據
第1份 27 16
第2份 26 17
第3份 25 18
第4份 24 19
第5份 23 20
第6份 22 21
剩下1~15搜索出6等份分給所有人
這樣成對出現的數蛇形數我們去處儘量多的偶數條
保證剩下的數的個數大於等於2*m小於4*m個
所以剩下的小於4m(小於40)個數我們只解用搜索就好了
所以n 的範圍就變成1~40,m的範圍1~10這樣我們記錄這些的結果(防止這樣的數據大量重複出現)
這樣如果我們有數據15 6計算過後
n=27 m= 6
n=39 m=6
n=15+(任意被的12) m=6
我們都不需要搜索了
就這樣這個問題就解決了
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#define maxn 100005
#define ll __int64
#define cnm c[nu][m]
using namespace std;
int v[15][maxn];
ll m,n;
//fun函數定義將1-num平均分給l-r個人
int a[15][50];
int si[15];
bool b[50];
int dp[50][10]={0};
int c[50][10][15][50]={0};
ll ave,nu;
bool dfs(int sum,int g,int s){
if(sum==ave){g++;sum=0;s=1;}
if(g==m-1){
for(int i=1;i<=nu;i++)
if(!b[i])a[g][++a[g][0]]=i;
return true;
}
for(int i=s;i<=nu;i++){
if(sum+i>ave) return false;
if(!b[i]){
b[i]=true;
a[g][++a[g][0]]=i;
if(dfs(sum+i,g,i+1)) return true;
b[i]=false;
a[g][0]--;
}
}
return false;
}
bool fun(ll num){
if(num>=4*m-1){
for(int i=0,j=0;i<m;i++,j++){
v[i][si[i]++]=num-j;
v[i][si[i]++]=num-2*m+1+j;
}
return fun(num-2*m);
}
else {
nu=num;
ave=(num+1)*num/2/m;
int b;
if(dp[num][m]==0){
if(dfs(0,0,1)){
dp[num][m]=1;
for(int i=0;i<m;i++)
for(int j=0;j<=a[i][0];j++)
cnm[i][j]=a[i][j];
}
else dp[num][m]=-1;
}
if(dp[nu][m]==1) return true;
return false;
}
}
void out(int n){
printf("YES\n");
for(int i=0;i<n;i++){
printf("%d",si[i]+cnm[i][0]);
for(int j=0;j<si[i];j++) printf(" %d",v[i][j]);
for(int j=0;j<cnm[i][0];j++) printf(" %d",cnm[i][j+1]);
printf("\n");
}
}
void Init(){
memset(si,0,sizeof(si));
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
}
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%I64d%I64d",&n,&m);
ll su=n*(n+1)/2;
ll av=su/m;
if(su%m||av<n)printf("NO\n");
else{
Init();
bool ok=fun(n);
if(ok)out(m);
else printf("NO\n");
}
}
return 0;
}
/*
此代碼存在侷限性數據更新後已不能在AC
待更新……
*/
這個題目看上去的時候第一感覺就是暴力,結果真的一遍就過了
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#define maxn 100005
#define ll __int64
using namespace std;
int a[maxn];
vector <int > v[maxn];
int main(){
int T;
scanf("%d",&T);
while(T--){
ll n,m;
scanf("%I64d%I64d",&n,&m);
ll sum =(n+1)*n/2;
if(sum%m==0){
ll ave=sum/m;
if(ave<n)
printf("NO\n");
else{
memset(v,0,sizeof(v));
memset(a,0,sizeof(a));
int t=ave,A=0;
int flag=0;
for(int i=n;!flag&&i>=1;i--){
if(a[i]==0){
t-=i;
v[A].push_back(i);
a[i]=1;
}
if(i-1>t){
for(int j=i-1;t&&j>=1;j--){
if(t>=j&&a[j]==0){
v[A].push_back(j);
t-=j;
a[j]=1;
}
}
}
if(t==0){
t=ave;
A++;
}
}
if(A==m){
printf("YES\n");
for(int i=0;i<m;i++){
printf("%d",v[i].size());
for(int j=0;j<v[i].size();j++)
printf(" %d",v[i][j]);
printf("\n");
}
}
else
printf("NO\n");
}
}
else
printf("NO\n");
}
return 0;
}