其他分享
首页 > 其他分享> > CSP-S模拟2(联考) 谜之阶乘 子集 混凝土粉末 排水系统

CSP-S模拟2(联考) 谜之阶乘 子集 混凝土粉末 排水系统

作者:互联网

rank 40 40多分?

T1:暴力;T2:构造

T2:构造出(1--n)的连续整数分成k组,每组的数加起来一样。(n<=1e6)

image
只要能实现一种构造方案,使得3k个连续数字分k组可以达到(a+b+c)相同(或2k,很显然)
构造方法:
1 8 15
2 9 13
3 10 11
4 6 14
5 7 12
很玄学,积累下来吧?

点击查看代码






#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define rint register int
#define chu printf
#define _f(i,a,b) for(rint i=a;i<=b;++i)
#define f_(i,a,b)  for(rint i=a;i>=b;--i)
inline ll re()
{
	ll x=0,h=1;char ch=getchar();
	while(ch<'0'||ch>'9')
	{
		if(ch=='-')h=-1;ch=getchar();
	}
	while(ch<='9'&&ch>='0')
	{
		x=(x<<1)+(x<<3)+(ch^48);
		ch=getchar();
	}
	return x*h;
}
const int N=0;
int n,k,T;
ll val,ev;//ev:每组的加和是多少
//val:一共的值,k:一共几组
vector<int>g[1000000+10];//k是多少就开多少
inline void special_deal()
{
	int cnt=n/k;
	int to2=cnt%3,to3;
	if(to2==1)to2+=3,to3=cnt-to2;
	else if(!to2)to3=cnt;
	//1 999957 333319

	else if(to2==2)to3=cnt-2;//3和2的都分多少组
	//先分3的
	to3/=3;int tiao=3*k;ll sumbase=((ll)3*k+1)*((ll)3*k)/2/k;
	//chu("to3:%d\n",to3);
	_f(i,1,to3)
	{
		int sta=tiao*(i-1);
		_f(j,1,k)
		g[j].push_back(++sta);//第一列放顺序
		_f(j,k/2+2,k)
		g[j].push_back(++sta);
		_f(j,1,k/2+1)
		g[j].push_back(++sta);
		ll sum=sumbase+tiao*3*(i-1);//3个一组每组的和
		_f(j,1,k)
		{
			int pos=g[j].size()-1;
			g[j].push_back(sum-(ll)g[j][pos]-(ll)g[j][pos-1]);
		//	chu("insert:%lld\n",sum-(ll)g[j][pos]-(ll)g[j][pos-1]);
		}
	}
	if(!to2)return;
	int l=k*to3*3+1,r=n;
	to3=to3*k*3+1;
	//chu("l:%d r:%d\n",l,r);
	while(1)
	{
		_f(i,1,k)
		g[i].push_back(l),g[i].push_back(n-l+to3),++l;;
		to2-=2;
		if(!to2)break;
	}
}
int main()
{
	//freopen("b.in","r",stdin);
	//freopen(""."w",stdout);
	T=re();
	while(T--)
	{
		_f(i,1,k)g[i].clear();
		n=re(),k=re();
		if(k==1)
		{
			chu("Yes\n");
			_f(i,1,n)chu("%d ",i);
			chu("\n");
			continue;
		}
		if(k==n)
		{
			chu("No\n");continue;
		}
		val=(1+n)*(ll)n/2;
		ev=val/k;int cnt=n/k;//cnt是每组多少个
		if(ev*k!=val)
		{
			chu("No\n");continue;
		}
		if(ev<n)
		{
			chu("No\n");continue;
		}
		if(!(cnt&1))
		{
			chu("Yes\n");
			int pos=0;
			_f(i,1,k)//第几组
			{
				_f(j,1,cnt/2)//每组几个
				{
					++pos;
					chu("%d %d ",pos,n-pos+1);
				}
				chu("\n");
			}
		}
		else
		{
			special_deal();
			chu("Yes\n");
			_f(i,1,k)
			{
				for(rint to:g[i])
				chu("%d ",to);
				chu("\n");
			}
		}
	}
	return 0;
}
/*
20
1 1
18 3
15 3
15 5
9 3
13 1
4 4
12 1
8 4
5 1
11 1
11 11
8 8
3 1
12 4
6 1
16 8
14 14
4 1
12 2
*/

标签:to2,to3,ll,back,CSP,int,chu,阶乘,联考
来源: https://www.cnblogs.com/403caorong/p/16655429.html