zoukankan      html  css  js  c++  java
  • 解题报告 noi 2002 robot

    机器人M号

     

     

    【问题描述】

    3030年,Macsy正在火星部署一批机器人。

    1秒,他把机器人1号运到了火星,机器人1号可以制造其他的机器人。

    2秒,机器人1号造出了第一个机器人——机器人2号。

    3秒,机器人1号造出了另一个机器人——机器人3号。

    之后每一秒,机器人1号都可以造出一个新的机器人。第m秒造出的机器人编号为m。我们可以称它为机器人m号,或者m号机器人。

     

    机器人造出来后,马上开始工作。m号机器人,每m秒会休息一次。比如3号机器人,会在第6912,……秒休息,而其它时间都在工作。

    机器人休息时,它的记忆将会被移植到当时出生的机器人的脑中。比如6号机器人出生时,23号机器人正在休息,因此,6号机器人会收到第23号机器人的记忆副本。我们称第23号机器人是6号机器人的老师。

    如果两个机器人没有师徒关系,且没有共同的老师,则称这两个机器人的知识是互相独立的。注意:1号机器人与其他所有机器人的知识独立(因为只有1号才会造机器人),它也不是任何机器人的老师。

     

    一个机器人的独立数,是指所有编号比它小且与它知识互相独立的机器人的个数。比如1号机器人的独立数为02号机器人的独立数为11号机器人与它知识互相独立),6号机器人的独立数为215号机器人与它知识互相独立,23号机器人都是它的老师,而4号机器人与它有共同的老师——2号机器人)。

    新造出来的机器人有3种不同的职业。对于编号为m的机器人,如果能把m分解成偶数个不同奇素数的积,则它是政客,例如编号15;否则,如果m本身就是奇素数或者能把m分解成奇数个不同奇素数的积,则它是军人,例如编号 3, 编号165。其它编号的机器人都是学者,例如编号2, 编号6, 编号9

     

    m秒诞生的机器人m号,想知道它和它的老师中,所有政客的独立数之和,所有军人的独立数之和,以及所有学者的独立数之和。可机器人m号忙于工作没时间计算,你能够帮助它吗?

    为了方便你的计算,Macsy已经帮你做了m的素因子分解。为了输出方便,只要求输出总和除以10000的余数。

     

    【输入文件】

    输入文件robot.in的第一行是一个正整数k(1<=k<=1000),km的不同的素因子个数。

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

     

    【输出文件】

    输出文件robot.out包括三行。

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

    第二行是机器人m号和它的老师中,所有军人的独立数之和除以10000的余数。

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

     

    【样例输入】

    3

    2  1

    3  2

    5  1

     

    【样例输出】

    8

    6

    75

     

    【样例说明】

        。90号机器人有10个老师,加上它自己共11个。其中政客只有15号;军人有3号和5号;学者有8个,它们的编号分别是:2,6,9,10,18,30,45,90

     

    【评分标准】

    输出文件包含三个数。如果你的程序算对了三个数,该测试点得10分;如果你的程序算对了两个数,该测试点得7分;如果你的程序算对了一个数,该测试点得4分;如果你的程序一个数也没算对,该测试点得0分;

     

     

     

     

     

     

    不难得出,每个数的独立数是与它互质的,所以这个数的独立数的个数就是他的欧拉函数。

    首先,说一个定理:一个数的所有因子的欧拉函数和为这个数减一。证明嘛,本蒟蒻不会。。。。。。

    然后嘞,至于军人和政客,是这么求的:

    f[i,j]:=(f[i-1,j]+f[i-1,j-1]*(a[i,1]-1))  (其中 ,a[i,1] 为每一个质因子,a[i,2] 为每一个质因子的指数)

    然后,不要忘了特判质因子为 2 的时候,然后政客:sigma(f[n,i],i mod 2=0)  军人:sigma(f[n,i],i mod 2<>0) 学者是用这个数所有因子的欧拉函数和减去前两个数。

    然后,不要忘了用快速幂。

    再然后,快速幂的时候,存 sqrt(ans) 的时候要用 int64 。

    再再然后,快速幂要这么写:

     

    function ks(d,z:longint):longint; inline;
    var temp:int64;
    begin
    if z=1 then exit(d);
    if z=0 then exit(1);

     

     

     

    temp:=ks(d,z>>1) mod 10000;
    if z mod 2=0 then exit((temp*temp) mod 10000)
    else exit((temp*temp*d) mod 10000);
    end;

    不要这么写:

    function ks(d,z:longint):longint; inline;
    begin
    if z=1 then exit(d);
    if z=0 then exit(1);

     

    if z mod 2=0 then exit((ks(d,z>>1)*ks(d,z>>1)) mod 10000)
    else exit(((ks(d,z>>1)*ks(d,z>>1)) mod 10000*d) mod 10000);
    end;

    因为这样是算两遍啊白痴!

     

     

     

     

     

     

    代码 SueMiller

     

    {$inline on}
    program ACRush;
    var i,j,k,n,tot:longint;
    a:array[0..1010,1..2]of longint;
    f:array[0..1010,0..1010]of integer;
    ans1,ans2,ans3:longint;

    function ks(d,z:longint):longint; inline;
    var temp:int64;
    begin
    if z=1 then exit(d);
    if z=0 then exit(1);

    temp:=ks(d,z>>1) mod 10000;
    if z mod 2=0 then exit((temp*temp) mod 10000)
    else exit((temp*temp*d) mod 10000);
    end;

    begin
    // assign(input,'robot.in');reset(input);
    // assign(output,'robot.out');rewrite(output);
    readln(n);
    ans3:=1;
    readln(a[1,1],a[1,2]);
    if a[1,1]=2 then
    begin
    ans3:=(ans3*ks(2,a[1,2])) mod 10000;
    k:=1;
    dec(n);
    end
    else k:=2;

    for i:=k to n do
    begin
    readln(a[i,1],a[i,2]);
    end;
    for i:=1 to n do
    begin
    ans3:=(ans3*ks(a[i,1],a[i,2])) mod 10000;
    // writeln('^^^ ',ks(a[i,1],a[i,2]));
    end;


    // writeln(ans3);
    f[0,0]:=1;
    for i:=1 to n do
    begin
    f[i,0]:=1;
    for j:=1 to i do
    begin
    f[i,j]:=(f[i-1,j-1]*(a[i,1]-1)+f[i-1,j]) mod 10000;
    end;
    end;
    for i:=n downto 1 do
    begin
    if i=((i>>1)<<1) then inc(ans1,f[n,i])
    else inc(ans2,f[n,i]);
    // writeln(i,' ',f[n,i],' &&');
    end;


    if ans1>10000 then ans1:=ans1 mod 10000;
    if ans2>10000 then ans2:=ans2 mod 10000;
    ans3:=ans3-ans1-ans2-1;
    while ans3<0 do inc(ans3,10000);
    writeln(ans1);
    writeln(ans2);
    writeln(ans3);
    // close(input);close(output);
    end.

  • 相关阅读:
    用学习逃避成长,听新知缓解焦虑
    谈谈“人”和“技能”
    SpringMVC的工作原理
    Spring MVC 处理静态资源文件
    nrpe的安装设置
    Maatkit工具使用&lt;一&gt;之mysql主从数据校验工具
    phpcgi占用cpu100%的一次排障之旅
    nginx支持cgi
    如何查看服务器RAID卡信息的SHELL脚本和命令介绍
    Mysql的一次经典故障
  • 原文地址:https://www.cnblogs.com/SueMiller/p/2367568.html
Copyright © 2011-2022 走看看