zoukankan      html  css  js  c++  java
  • [noi2002]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的余数。

    可以看出独立数就是欧拉函数值;

    设f[i][j]表示前i个约数中选j个约数的欧拉函数值;

    由于欧拉函数的是积性函数;

    f[i][j]=f[i-1][j]+f[i-1][j-1]*(p[i]-1);相当于f[i][j]既可以由不选i得到,又可以从一定选i得到;

    然后j%2=1的f[k][j]加起来得到了军人的,j%2==0的f[k][j]加起来得到了政客的;

    欧拉函数有一个性质,m的约数的欧拉函数和是m;

    然后m-ans1-ans2-1,得到了学者的;

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<string>
     5 #include<cstdlib>
     6 #include<ctime>
     7 #include<vector>
     8 #include<algorithm>
     9 #include<queue>
    10 #include<map>
    11 using namespace std;
    12 #define LL long long
    13 const int mod=10000;
    14 int k;
    15 int c[1010][2],f[1010];
    16 int mi(int a,int b){
    17     int ans=1;
    18     while(b){
    19         if(b%2)ans=(ans*a)%mod;
    20         b/=2;
    21         a=(a*a)%mod;
    22     }
    23     return ans;
    24 }
    25 void init(){
    26     scanf("%d",&k);
    27     for(int i=1;i<=k;i++)scanf("%d%d",&c[i][0],&c[i][1]);
    28 }
    29 void work(){
    30     int ans1=0,ans2=0,ans=1,g;
    31     if(c[1][0]==2)g=2;
    32     else g=1;
    33     f[0]=1;
    34     for(int i=g;i<=k;i++)
    35         for(int j=i-g+1;j>=1;j--)
    36             f[j]=(f[j]+f[j-1]*(c[i][0]-1))%mod;
    37     for(int i=1;i<=k-g+1;i++){
    38         if(i%2)ans1=(ans1+f[i])%mod;
    39         else ans2=(ans2+f[i])%mod;
    40     }
    41     for(int i=1;i<=k;i++)ans=(ans*mi(c[i][0],c[i][1]))%mod;
    42     ans=(ans+10000000-ans1-ans2-1)%mod;
    43     printf("%d
    %d
    %d
    ",ans2,ans1,ans);
    44     return;
    45 }
    46 int main(){
    47     freopen("1.in","r",stdin);
    48     freopen("1.out","w",stdout);
    49     init();
    50     work();
    51     return 0;
    52 }
    View Code
  • 相关阅读:
    注意:开发环境不同,启动代码不同…
    6410在rvds下编译启动代码报错分析
    S3C6410的启动代码分析&nbsp;一
    s3c6410开发板LED驱动程序设计详细…
    季逸超:90后IT少年的“盖茨梦”
    我的博客今天0岁52天了,我领取了…
    在linux中获取错误返回信息&nbsp;&amp;…
    各种居中对齐
    文本对齐方式
    素描人像
  • 原文地址:https://www.cnblogs.com/chadinblog/p/5881373.html
Copyright © 2011-2022 走看看