【JZOJ3156】病毒傳播

description

病毒擴散了!村莊中共有M 個人,編號爲0 到M-1,病毒症狀只會持續一

天,每個人可能多次感染病毒。

第一天,若干個病毒攜帶者感染了病毒,病毒擴散就是由病毒攜帶者引起的,

從第二天開始的每一天,編號P 的人在以下條件下就會感染病毒:

(a*b)mod M=P

(其中a 爲前一天感染病毒的某一個人的編號,b 是其中一個病毒攜帶者的編

號,a 和b 可能相同)

例如村莊共101 個人,病毒攜帶者編號爲5 和50,第一天感染病毒的爲5

和50,第二天有25,48(250 mod 101)和76(2500 mod 101),第三天77 會感染病

毒,因爲(48*50) mod 101=77

問第K 天哪些人會感染病毒。


analysis

  • 首先暴力把兩天的東西相乘起來誰都會,O(n2)O(n^2)

  • 考慮f[i]f[i]表示第ii天的答案,那麼f[i]=f[i1]Af[i]=f[i-1]*A,這個AA就是原數組

  • 對於這個東西,快速冪就好了

  • 時間複雜度O(n2log2k)O(n^2\log_2k)


code

#pragma GCC optimize("O3")
#pragma G++ optimize("O3")
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define MAXN 1505
#define ll long long
#define reg register ll
#define fo(i,a,b) for (reg i=a;i<=b;++i)
#define fd(i,a,b) for (reg i=a;i>=b;--i)
#define O3 __attribute__((optimize("-O3")))

using namespace std;

bool bz[MAXN];
ll n,m,k;

struct node
{
	ll f[MAXN];
}ans,a;

O3 inline ll read()
{
	ll x=0,f=1;char ch=getchar();
	while (ch<'0' || '9'<ch){if (ch=='-')f=-1;ch=getchar();}
	while ('0'<=ch && ch<='9')x=x*10+ch-'0',ch=getchar();
	return x*f;
}
O3 inline void mul(node &a,node &b)
{
	if (a.f[0]==-1){a=b;return;}
	memset(bz,0,sizeof(bz));
	fo(i,1,a.f[0])fo(j,1,b.f[0])
		bz[a.f[i]*b.f[j]%n]=1;
	a.f[0]=0;
	fo(i,0,n-1)if (bz[i])a.f[++a.f[0]]=i;
}
O3 int main()
{
	//freopen("T3.in","r",stdin);
	k=read(),n=read(),a.f[0]=read(),ans.f[0]=-1;
	fo(i,1,a.f[0])a.f[i]=read();
	while (k)
	{
		if (k&1)mul(ans,a);
		mul(a,a),k>>=1;
	}
	fo(i,1,ans.f[0])printf("%lld ",ans.f[i]);
	printf("\n");
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章