1. 程式人生 > >NKOJ 3804 機器人M號(遞推+尤拉函式)

NKOJ 3804 機器人M號(遞推+尤拉函式)

P3804機器人 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是不同的素數,m=ki=1peii
所有素因子按照從小到大排列,即 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

首先考慮政客和軍人,由於政客再乘上一個新的質數變成軍人,而軍人乘上一個新的質數變成政客,那麼令F[i][0]表示前i個軍人的ϕ之和,F[i][1]表示前i個政客的ϕ之和,那麼有

F[i][0]=F[i1][0]+F[i1][1]×ϕ(A[i])
F[i][1]=F[i1][1]+F[i1][0]×ϕ(A[i])
於是遞推即可求出政客和軍人的獨立數之和,然後背出公式
n
=d|nϕ(d)

於是學者的獨立數之和等於mF[k][0]F[k][1]

程式碼:

#include<stdio.h>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
ll k,A[1234],E[1234],F[1234][2],mod=10000,m=1;
ll QM(ll a,ll b)
{
    ll ans=1;
    while(b)
    {
        if(b&1)ans=ans*a%mod;
        b>>=1;
        a=a*a%mod;
    }
    return ans;
}
int main()
{
    ll i;
    scanf("%lld",&k);
    for(i=1;i<=k;i++)scanf("%lld%lld",&A[i],&E[i]);
    if(A[1]==2)F[1][0]=1;
    else F[0][0]=1;
    for(i=1;i<=k;i++)
    {
        if(A[i]==2)continue;
        F[i][0]=(F[i-1][0]+F[i-1][1]*(A[i]-1))%mod;
        F[i][1]=(F[i-1][1]+F[i-1][0]*(A[i]-1))%mod;
    }
    F[k][0]--;
    for(i=1;i<=k;i++)m=m*QM(A[i],E[i])%mod;
    m=(m-F[k][0]-F[k][1]-1)%mod;
    m%=mod;m+=mod;m%=mod;
    printf("%lld\n%lld\n%lld",F[k][0],F[k][1],m);
}