jzoj1161-机器人M号【欧拉函数,dp】

正题


大意

因为题目比较gou,所以就直接放题目了

机器人1号可以制造其他的机器人。 第2秒,机器人1号造出了第一个机器人——机器人2号。 第3秒,机器人1号造出了另一个机器人——机器人3号。 之后每一秒,机器人1号都可以造出一个新的机器人。第m秒造出的机器人编号为m。我们可以称它为机器人m号,或者m号机器人。 机器人造出来后,马上开始工作。m号机器人,每m秒会休息一次。比如3号机器人,会在第6,9,12,……秒休息,而其它时间都在工作。 机器人休息时,它的记忆将会被移植到当时出生的机器人的脑中。比如6号机器人出生时,2,3号机器人正在休息,因此,6号机器人会收到第2,3号机器人的记忆副本。我们称第2,3号机器人是6号机器人的老师。 如果两个机器人没有师徒关系,且没有共同的老师,则称这两个机器人的知识是互相独立的。注意:1号机器人与其他所有机器人的知识独立(因为只有1号才会造机器人),它也不是任何机器人的老师。 一个机器人的独立数,是指所有编号比它小且与它知识互相独立的机器人的个数。比如1号机器人的独立数为0,2号机器人的独立数为1(1号机器人与它知识互相独立),6号机器人的独立数为2(1,5号机器人与它知识互相独立,2,3号机器人都是它的老师,而4号机器人与它有共同的老师——2号机器人)。 新造出来的机器人有3种不同的职业。对于编号为m的机器人,如果能把m分解成偶数个不同奇素数的积,则它是政客,例如编号15;否则,如果m本身就是奇素数或者能把m分解成奇数个不同奇素数的积,则它是军人,例如编号 3, 编号165。其它编号的机器人都是学者,例如编号2, 编号6, 编号9。 第m秒诞生的机器人m号,想知道它和它的老师中,所有政客的独立数之和,所有军人的独立数之和,以及所有学者的独立数之和。可机器人m号忙于工作没时间计算,你能够帮助它吗? 为了方便你的计算,Macsy已经帮你做了m的素因子分解。为了输出方便,只要求输出总和除以10000的余数。


解题思路

首先一个机器人m的独立数是 φ ( m ) \varphi(m) φ(m)而老师的数量就是他的因数数量-2,然后把M分解为
p 1 e 1 × p 2 e 2 × p 3 e 3 . . . × p k e k p1^{e1}\times p2^{e2}\times p3^{e3}...\times pk^{ek} p1e1×p2e2×p3e3...×pkek
然后
φ ( m ) = p 1 e 1 × p 2 e 2 . . . × p k e k × ( 1 − 1 p 1 ) × ( 1 − 1 p 2 ) . . . × ( 1 − 1 p k ) \varphi(m)=p1^{e1}\times p2^{e2}...\times pk^{ek}\times (1-\frac{1}{p1})\times (1-\frac{1}{p2})...\times (1-\frac{1}{pk}) φ(m)=p1e1×p2e2...×pkek×(1p11)×(1p21)...×(1pk1)
之后
φ ( m ) = ( p 1 − 1 ) p 1 e 1 − 1 × ( p 2 − 1 ) p 2 e 2 − 1 . . . × ( p k − 1 ) p k e k − 1 \varphi(m)=(p1-1)p1^{e1-1}\times (p2-1)p2^{e2-1}...\times (pk-1)pk^{ek-1} φ(m)=(p11)p1e11×(p21)p2e21...×(pk1)pkek1
然后我们就可以发现政客的独立数就是在M的奇质因数中选择偶数个不同的乘起来的欧拉函数,军人就是选奇数个。然后学者就是M所以的独立数减去政客和军人。
选数我们可以用dp
f [ i   m o d   2 ] [ 0 ] f[i\ mod\ 2][0] f[i mod 2][0]表示在M因子中只包含前i个的政客的欧拉函数
f [ i   m o d   2 ] [ 1 ] f[i\ mod\ 2][1] f[i mod 2][1]表示在M因子中只包含前i个的政客的欧拉函数
然后进行动态转移
f [ i   m o d   2 ] [ 0 ] = f [ ( i + 1 )   m o d   2 ] [ 0 ] + f [ ( i + 1 )   m o d   2 ] [ 1 ] ∗ ( p − 1 ) f[i\ mod\ 2][0]=f[(i+1)\ mod\ 2][0]+f[(i+1)\ mod\ 2][1]*(p-1) f[i mod 2][0]=f[(i+1) mod 2][0]+f[(i+1) mod 2][1](p1)
f [ i   m o d   2 ] [ 1 ] = f [ ( i + 1 )   m o d   2 ] [ 1 ] + f [ ( i + 1 )   m o d   2 ] [ 0 ] ∗ ( p − 1 ) f[i\ mod\ 2][1]=f[(i+1)\ mod\ 2][1]+f[(i+1)\ mod\ 2][0]*(p-1) f[i mod 2][1]=f[(i+1) mod 2][1]+f[(i+1) mod 2][0](p1)
最后计算 φ ( m ) \varphi(m) φ(m)减去最后的政客独立数总和和军人独立数总和


代码

#include<cstdio>
#define mods 10000
using namespace std;
int n,p,e,f[2][2],m=1;
int ksm(int x,int k)//快速幂
{
	int ans=1;
	while (k)
	{
		if (k&1) ans=(ans*x)%mods;
		x=x*x%mods;
		k/=2;
	}
	return ans;
}
int main()
{
	scanf("%d",&n);
	scanf("%d%d",&p,&e);
	m=m*ksm(p,e)%mods;
	if (p==2) f[1][0]=1;
	else
	{
		f[0][0]=1;
		f[1][0]=(f[0][0]+f[0][1]*(p-1)%mods)%mods;
		f[1][1]=(f[0][1]+f[0][0]*(p-1)%mods)%mods;
	}//初始化(sro xjqのdalao orz)
	for (int i=2;i<=n;i++)
	{
		scanf("%d%d",&p,&e);
		m=m*ksm(p,e)%mods;
		f[i&1][0]=(f[~-i&1][0]+f[~-i&1][1]*(p-1)%mods)%mods;
		f[i&1][1]=(f[~-i&1][1]+f[~-i&1][0]*(p-1)%mods)%mods;
		//动态转移
	}
	f[n&1][0]--;m=((m-1-f[n&1][0]-f[n&1][1])%mods+mods)%mods;//计算学者
	printf("%d\n%d\n%d",f[n&1][0],f[n&1][1],m);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值