题目
分析
这道题足以显示我 (dp) 水平真是菜到家了。。才做了不久又不会了。。
首先题目里面说:
对于编号为 (m) 的机器人,如果能把 (m) 分解成偶数个不同奇素数的积,则它是政客,例如编号 (15);
否则,如果 (m) 本身就是奇素数或者能把 (m) 分解成奇数个不同奇素数的积,则它是军人,例如编号 (3),编号 (165)。
其它编号的机器人都是学者,例如编号 (2), 编号 (6), 编号 (9)。
注意到不同奇素数,发现这样的数很少,但是我们还是没办法暴力,不过,因为要求不同,那么每一个数只有 选/不选 两种情况,这让我们想到了什么,(dp) !
于是设状态 (dp[i,0/1]) 表示:前 (i) 个质因子可以构成的所有数当中,选了偶数个数/奇数个数的所有数的独立数之和。
根据当前这个质数选和不选两种情况,有转移方程:(large dp[i,v]=dp[i-1,v^1] imes varphi{(prime[i])}+dp[i-1,v])
然后学者的人数就简单运用减法原理一下即可。
代码
#include<bits/stdc++.h>
using namespace std;
template <typename T>
inline void read(T &x){
x=0;char ch=getchar();bool f=false;
while(!isdigit(ch)){if(ch=='-'){f=true;}ch=getchar();}
while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
x=f?-x:x;
return ;
}
template <typename T>
inline void write(T x){
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10^48);
return ;
}
const int N=1e6+5,M=1e6+5,MOD=10000;
#define ll long long
int n,p,c,dp[N][2];
inline int QuickPow(int x,int y){
int res=1;
while(y){
if(y&1) res=res*x%MOD;
x=x*x%MOD;
y>>=1;
}
return res;
}
int main(){
read(n);int tmp=1;
dp[0][0]=1;
for(int i=1;i<=n;i++){
read(p),read(c);
tmp=tmp*QuickPow(p,c)%MOD;
dp[i][0]=(dp[i-1][1]*(p==2?0:p-1)+dp[i-1][0])%MOD;
dp[i][1]=(dp[i-1][0]*(p==2?0:p-1)+dp[i-1][1])%MOD;
}
dp[n][0]=(dp[n][0]-1+MOD)%MOD;
write(dp[n][0]),putchar('
'),write(dp[n][1]),putchar('
'),write(((tmp-dp[n][0]-dp[n][1]-1)%MOD+MOD)%MOD);
return 0;
}