【GDOI2013模拟1】病毒传播

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Larry1118/article/details/87893644

这题是个类似矩乘的东西。。。
我们要求的是第K天的感染人数。
然后我们可以证明出来这个满足结合律(易得(a * b) * b=a * (b * b))
而题目求的就是bk,所以我们就可以像快速幂一样求bk
O(log(k)*n2)
所以就可以用矩乘啦。
上标:

#include<cstdio>
#include<cstring>
#define N 1510
using namespace std;
int m,a[N],s[N],bz[N],tot=0;
long long K;

inline int read()
{
	int x=0; char c=getchar();
	while (c<'0' || c>'9') c=getchar();
	while (c>='0' && c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
	return x;
}

int main()
{
	freopen("virus.in","r",stdin);
//	freopen("virus.out","w",stdout);
	scanf("%lld",&K),m=read(),a[0]=read();
	for (int i=1;i<=a[0];i++) a[i]=read();
	while (K)
	{
		if (K & 1)
		{
			if (!s[0])
			{
				memcpy(s,a,sizeof(a));
			}
			else
			{
				tot++;
				for (int i=1;i<=a[0];i++)
					for (int j=1;j<=s[0];j++)
						bz[a[i]*s[j]%m]=tot;
				s[0]=0;
				for (int i=0;i<m;i++)
					if (bz[i]==tot) s[++s[0]]=i;
			}
		}
		tot++;
		for (int i=1;i<=a[0];i++)
			for (int j=1;j<=a[0];j++)
				bz[a[i]*a[j]%m]=tot;
		a[0]=0;
		for (int i=0;i<m;i++)
			if (bz[i]==tot) a[++a[0]]=i;
		K>>=1;
	}
	for (int i=1;i<=s[0];i++)
		printf("%d ",s[i]);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Larry1118/article/details/87893644