题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1408
这么长的题面。。。是在告诉我们OI选手必须学好语文吗?
其实题目中的机器人n独立数就是phi(n),新定义phi(1)=0。机器人n的老师就是n的约数,与某个数有共同老师说明二者不互质。
直接在已经质因数分解的数上DP就好
ans1表示到目前质因子政客的独立数之和(即拥有偶数个质因子的数的欧拉函数之和)
ans2表示到目前质因子军人的独立数之和(即拥有奇数个质因子的数的欧拉函数之和)
注意不管是军人还是政客的质因子都是互异的
于是我们得到下面的状态转移方程:
int z=ans1; ans1=(ans1+ans2*(p-1))%mod;//政客 ans2=(ans2+(z+1)*(p-1))%mod;//军人
因为欧拉函数是积性函数,所以每多加一个质因子p,独立数之和就会乘上p-1;计算ans2时之所以z要加1是因为新加的一个质因数p单独存在也会对答案做出贡献
那么学者呢?根据题意,不是军人,不是政客,当然也不是1号机器人的就是学者。于是学者的独立数之和等于数m的各个约数的独立数之和-1(1号机器人不算)-政客的独立数之和-军人的独立数之和
根据欧拉函数的定理之一,一个正整数的各个约数的欧拉函数值之和等于本身的值
还需要注意2遇到要跳过
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=1000+15; const int mod=10000; int k,m,ans1,ans2,p,e; inline int read() { char ch=getchar(); int s=0,f=1; while (!(ch>='0'&&ch<='9')) {if (ch=='-') f=-1;ch=getchar();} while (ch>='0'&&ch<='9') {s=(s<<3)+(s<<1)+ch-'0';ch=getchar();} return s*f; } int pow(int x,int e) { int r=1; while (e) { if (e&1) r=r*x%mod; x=x*x%mod;e>>=1; } return r; } int main() { k=read(); m=1; for (int i=1;i<=k;i++) { p=read();e=read(); m=m*pow(p,e)%mod; if (p==2) continue; int z=ans1; ans1=(ans1+ans2*(p-1))%mod;//政客 ans2=(ans2+(z+1)*(p-1))%mod;//军人 } printf("%d %d %d ",ans1,ans2,(m-1-ans1-ans2+3*mod)%mod); return 0; }