1. 程式人生 > >[數論][尤拉函式]機器人M號

[數論][尤拉函式]機器人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的餘數。

Input
輸入檔案的第一行是一個正整數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。

Output
輸出檔案包括三行。 第一行是機器人m號和它的老師中,所有政客的獨立數之和除以10000的餘數。 第二行是機器人m號和它的老師中,所有軍人的獨立數之和除以10000的餘數。 第三行是機器人m號和它的老師中,所有學者的獨立數之和除以10000的餘數。

Sample Input
3 2 1 3 2 5 1

Sample Output
8 6 75

分析

這題扯得有點牽強= =
獨立數其實就是尤拉函式值啦
有三個值:
1、奇數個奇素數的積的數的尤拉函式總值[f]
2、偶數個……[g]
3、除此之外的數的尤拉函式總值
然後我們因為知道尤拉函式具有如下性質:
φ(a*b)=φ(a)*φ(b)
φ(p)=p-1 (p為素數)
所以我們發現1、2是可以互相轉換的即
f[i]=g[i-1]*(p[i]-1)+f[i-1]
g[i]=f[i-1]*(p[i]-1)+g[i-1]
然後通過很複雜看題解的過程知道3的值就是m-f[k]-g[k]

#include <iostream>
#include <cstdio>
#define rep(i,a,b) for (i=a;i<=b;i++)
const int N=1001;
const int q=10000;
using namespace std;
int k;
struct num {
    int p,c;
}a[N];
int p[N],s[N],m=1;

int Power(int x,int y) {
    int ans=1;
    while (y) {
        if (y&1) ans=ans*x%q;
        x=x*x%q;
        y>>=1;
    }
    return ans;
}

int main() {
    int i;
    scanf("%d",&k);
    rep(i,1,k)
    scanf("%d%d",&a[i].p,&a[i].c);
    p[0]=1;
    if (a[1].p==2) p[1]=1;
    else s[1]=a[i].p-1;
    rep(i,1,k) {
        if (a[i].p==2) continue;
        p[i]=(s[i-1]*(a[i].p-1)%q+p[i-1])%q;
        s[i]=(p[i-1]*(a[i].p-1)%q+s[i-1])%q;
    }
    rep(i,1,k) m=m*Power(a[i].p,a[i].c)%q;
    printf("%d\n%d\n%d",p[k]-1,s[k],((m-s[k]-p[k])%q+q)%q);
}