题解 P6306 【「Wdsr-1」小铃的书】

水题解来了


开始讲

一步一步来吧,先是\(50pt\)

\(first--50pt\)

话说这个部分应该都会吧

其实这个部分就是把所有能想到的做法都拿出来爆搞就是了,比如存储后排序再扫描处理,或者直接用桶存

而我们现在关心的是后一种做法。为什么?我也不知道,因为这与我们之后的\(75pt\)以及正解的思路都密切相关。而\(50pt\)部分的桶做法应该都能想到吧,就是用个\(map\)暴力存储,再看最后的出现次数是否\(mod~k\)为零

\(second--75pt\)

可是\(map\)到了第二个部分\(75pt\)时,\(8mb\)会卡得你不要不要的,所以就只能考虑其它的巧了

依旧考虑桶的思路,而目标是优化空间,那么就考虑将一个数拆成其\(k\)进制的若干部分,比如\(k=3\)时,将\((5)_ {10}\)变成\((12)_ {3}\),而将\((12)_ {3}\)的个位\(2\)存入专门存个位的桶中,十位\(1\)存入专门存十位的桶中,这个存其实就是将数加入桶中。而将桶取模\(k\),若有剩余那么剩下的必然是可以计入答案中的,关于这个我们假设混入的魔导书为\(t\),其存入的某一位设为第\(p\)位,则其存入的数值是\(ans_p=\frac{t\% k^{p+1}}{k^p}\),而显然\(k^p<t\%k^{p+1}<k^{p+1}\),所以\(0<ans_p<\frac{k^{p+1}}{k^p}=k\)(以上除号均是下取整),所以膜\(k\)后剩下的值一定是答案中的,可以加入

也就是以下代码:

fac[0]=1;
for(register int i=1;fac[i-1]<=lim;up=i++)
	fac[i]=fac[i-1]*k;
for(register ll x;n;--n)
{
	x=read();
	for(register int i=up;x;--i)
		if(x>=fac[i])
		{
			ans[i]+=x/fac[i];
			if(ans[i]>=k)
				ans[i]-=k;
			x%=fac[i];
		}
}
for(register int i=up;~i;--i)
	res+=ans[i]*fac[i];

只给出了一部分,其中\(fac_i=k^i\),而\(res\)就是最后答案

\(third--100pt\)

而第二部分的空间\(O(log_2a_{max})\)是合格了,但显然时间\(O(nlog_ka_{max})\)被卡掉了,所以考虑进一步优化

继续考虑桶与拆分的思路,可以想到把\(second\)中的空间稍微开大一点以达到节约时间的目的

将一个数分成若干个部分,但这次不是统计那个部分的代数和了,而是统计某个数的该部分的出现次数,这样就可以成功解决问题了

比如将一个数\(a\)分为\(a_{1-8}\)\(8\)个部分,其中\(2^{8* (i-1)}<=a_i<2^{8* i}\),那么再建立\(8\)个数组\(ans_{i,j}\),其中\(ans_{i,a_i}\)自加,那么这些数组就跟一个个小桶一样了,时间也节约了很多,只是\(O(n)\)套了一个\(8\)的常数,而能顺利解决问题

至于开\(8\)个数组只是怕\(MLE\),其实应该可以开更小的,但\(8\)个已经够了,不会\(T\)

短小精悍的代码:

#include<bits/stdc++.h>
using namespace std;

#define ll long long

inline ll read()
{
	ll x=0,ch=getchar();
	for(;ch<'0'||ch>'9';ch=getchar());
	for(;ch>='0'&&ch<='9';ch=getchar()) x=(x<<1)+(x<<3)+(ch^48);
	return x;
}

const int digit=1<<8,p=8;

int a[p][digit];
ll ans,n,k;

int main()
{
	n=read(),k=read();
	for(register ll x;n;--n)
	{
		x=read();
		for(register int i=0;i<p;++i)
			++a[i][(x>>(i*p))&(digit-1)];
	}
	for(register ll i=1;i<digit;++i)
		for(register int j=0;j<p;++j)
			if(a[j][i]%k)
				ans+=(i<<(j*p));
	printf("%lld\n",ans);
	return 0;
}
posted @ 2020-04-10 14:59  wyd_forever  阅读(189)  评论(0)    收藏  举报