(\)
Description
(\)
Solution
垃圾语文题毁我青春
这题其实就是重定义了俩函数....
首先 (varphi(1)=0) 。
然后 (2) 在计算 (mu) 的时候不算做质因子,含 (2) 的数 (mu) 值 (=0) 。
求 (m) 的所有因数中 , (mu=1,-1,0) 的 (varphi) 值之和。
(\)
先考虑 (mu=1,-1) 的答案。
根据 (mu) 的定义,此时所有所求的数字都满足,分解质因数每一个质因数的质数至多为 (1) 。
然后 **仅对于这些数 ** 欧拉函数就有了一个新的计算公式:
[varphi(n)=n imes {frac{p_1-1}{p_1}} imes {frac{p_2-1}{p_2}} imes ... imes {frac{p_m-1}{p_m}}=(p_1-1) imes (p_2-1) imes ... imes (p_3-1)
]
发现这是一个质数集合选哪些的问题。
注意到每次多选一个质数,所有的数字答案都乘上了相同的数,所以可以直接求答案。
用一种类似动规的写法,依次考虑每一个位置选或不选。
记(ans_1)表示选奇数个质因子,(ans_2) 表示选偶数个质因子的答案。
[ans_1+=ans_2 imes (p_i-1),ans_2+=ans_1 imes (p_i-1)
]
可以思考一下加号连接的含义。
(\)
然后就只需要解决 (mu=0) 的部分了。
关于欧拉函数其实有一个等式
[sum_{d|m}varphi(d)=m
]
然后问题解决,答案就是 (m-ans_1-ans_2-1),之所以多减掉一个 (1) 是因为 (varphi(1)=0) 。
(\)
Code
#include<cmath>
#include<cstdio>
#include<cctype>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define mod 10000
#define R register
#define gc getchar
using namespace std;
inline int rd(){
int x=0; bool f=0; char c=gc();
while(!isdigit(c)){if(c=='-')f=1;c=gc();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=gc();}
return f?-x:x;
}
inline int qpow(int x,int t){
int res=1;
while(t){
if(t&1) (res*=x)%=mod;
(x*=x)%=mod; t>>=1;
}
return res;
}
int n,m=1,p,cnt,tmp,ansodd,anseven=1;
int main(){
int n=rd();
for(R int i=1;i<=n;++i){
p=rd(); cnt=rd();
(m*=qpow(p,cnt))%=mod;
if(p>2){
tmp=ansodd;
(ansodd+=anseven*(p-1))%=mod;
(anseven+=tmp*(p-1))%=mod;
}
}
printf("%d
%d
%d
",(anseven-1+mod)%mod,ansodd,((m-anseven-ansodd)%mod+mod)%mod);
return 0;
}