NOI 2002 机器人M号 欧拉函数

NKOJ3804 机器人 M 号

问题描述

3030 年,Macsy正在火星部署一批机器人。
第 1 秒,他把机器人 1 号运到了火星,机器人 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 的余数。

输入格式

第一行是一个正整数 k(1<=k<=1000),k 是 m 的不同的 素因子个数。
以下k行,每行两个整数, pi, ei,表示m的第i个素因子和它的指数(i = 1, 2, …, k)。
p1, p2, …, pk是不同的素数,。
所有素因子按照从小到大排列,即 p1 < p2 < …< pk。
2<=pi<10,000, 1<=ei<=1,000,000。

输出格式

包括三行。
第一行是机器人 m 号和它的老师中,所有政客的 独立数 之和除以 10000 的余 数。
第二行是机器人 m 号和它的老师中,所有军人的 独立数 之和除以 10000 的余 数。
第三行是机器人 m 号和它的老师中,所有学者的 独立数 之和除以 10000 的余 数。

样例输入

3
2 1
3 2
5 1

样例输出

8
6
75


挺不错的一道欧拉函数复习题。

首先把题目条件翻译一下:

给出一个数M的标准分解,现在求数M的因数当中:
(1)能被分解为奇数个奇素数相乘的数的欧拉函数值之和;
(2)能被分解为偶数个奇素数的数的欧拉函数值之和;
(3)除(1),(2)以外所有因数的欧拉函数之和(不含1)

对于(1)和(2),注意到乘上一个奇质数能使(1)(2)互相转化,不妨用f[i][0]表示讨论到第i个数时满足(2)的答案,f[i][1]表示讨论到第i个数时满足(1)的答案。考虑两种情况的递推关系。

这里要用到欧拉函数的一个性质:欧拉函数是积性函数,既当 gcd(a,b)=1 时,有 ϕ(a)×ϕ(b)=ϕ(a×b)

根据这个容易得到递推式:

f[i][0]=f[i1][1]×(p[i]1)+f[i1][0]
f[i][1]=f[i1][0]×(p[i]1)+f[i1][1]
(pϕ(p)=p1)

这样前两个问题都被解决了,考虑第三个问题。这又要用到欧拉函数的一个性质:

n=d|nϕ(d)

这样第三个问题就可以解决了,注意不含1。

代码:

#include<stdio.h>
#define MAXK 1005

int K,p[MAXK],e[MAXK],f[MAXK][2],M=1;
const int mod=10000;

int ksm(int a,int b)
{
    int ans=1;
    while(b)
    {
        if(b&1)ans=ans*a%mod;
        b>>=1;a=a*a%mod;
    }
    return ans;
}

int main()
{
    int i;

    scanf("%d",&K);
    for(i=1;i<=K;i++)scanf("%d%d",&p[i],&e[i]);

    f[0][0]=1;
    if(p[1]==2)f[1][0]=1;
    else f[1][1]=p[i]-1;

    for(i=1;i<=K;i++)
    {
        if(p[i]==2)continue;
        f[i][0]=(f[i-1][1]*(p[i]-1)%mod+f[i-1][0])%mod,f[i][1]=(f[i-1][0]*(p[i]-1)%mod+f[i-1][1])%mod;
    }

    for(i=1;i<=K;i++)M=M*ksm(p[i],e[i])%mod;

    M=((M-f[K][0]-f[K][1])%mod+mod)%mod;

    printf("%d\n%d\n%d",f[K][0]-1,f[K][1],M);
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
NOI2002是全国青少信息学奥林匹克竞赛的一个比赛份。测试数据在比赛前被用来验证和评估比赛的题目和程序。 测试数据在NOI2002中起着非常重要的作用。它们通过提供不同情况下的输入,测试和验证参赛者的程序的正确性和稳定性。这些数据可以涵盖各种可能的情况和边界条件,以确保参赛者的程序能够在各种场景下都能正确地运行。测试数据可以包括正常情况下的输入输出,特殊情况下的输入输出,以及极端情况下的输入输出等等。 具体来说,测试数据对于参赛者来说是非常重要的。参赛者需要根据题目要求,编写程序并自己进行调试测试。通过运行测试数据并检查输出结果,参赛者可以评估自己程序的正确性。如果程序不能正确运行,参赛者可以根据测试数据的输出结果来定位和修复错误。同时,测试数据也对于裁判和考评人员来说非常重要。他们可以使用测试数据来评估程序的正确性,并为参赛者打分。 在NOI2002中,测试数据的选择和设计需要经过精心考虑和权衡。测试数据的覆盖范围应该尽可能广泛,以涵盖各种可能的情况和边界条件。此外,测试数据应该具有代表性,能够反映实际问题的性质和要求。通过这样的测试数据,才能够公平地评估参赛者的能力和程序的质量。 总而言之,测试数据是NOI2002中非常重要的一部分。它们用于验证和评估参赛者的程序,确保程序的正确性和稳定性。测试数据的选择和设计需要经过精心考虑,以保证公平和有效性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值