1、题面:
2、思路:
(参考文章)
将题中的公式化简,可以得到
对第一个样例有:ans = 6 *(1 + (1-1/2) + (1-1/3) + (1-1/3)*(1-1/2) ),
所以有:ans = 6*(1+1/2+2/3+1/3);
对第二个样例有:ans = 36*(1+1/2+1/2+2/3+2/3+1/3+1/3+1/3+1/3) = 168
可以得到ans = n*k*(1-p)/p(k表示有质数的次数,p表示质数的大小)。
法一:
直接利用上面的公式来做,每次对第i个数分为取,不取两种情况,
复杂度为m^2.
法二:
将上述公式化简为
直接利用公式求解即可。
3、代码:
法一代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;
const LL MOD = 998244353;
int m;
LL inv[25],p[25],q[25],ans;
LL POW(LL a,LL b){
LL res = 1LL;
while(b){
if(b&1LL){
res = res*a%MOD;
}
b/=2;
a = a*a%MOD;
}
return res;
}
void dfs(int pos,LL sum){
if(pos==m){
ans = (ans+sum)%MOD;
return ;
}
dfs(pos+1,sum);
dfs(pos+1,sum*q[pos]%MOD*(p[pos]-1LL)%MOD*inv[pos]%MOD);
}
int main(void){
int T;
scanf("%d",&T);
while(T--){
scanf("%d",&m);
LL sum = 1LL;
ans = 0;
for(int i=0;i<m;i++){
scanf("%lld%lld",&p[i],&q[i]);
inv[i] = POW(p[i],MOD-2);
sum = sum*POW(p[i],q[i])%MOD;
}
dfs(0,sum);
printf("%lld\n",ans);
}
return 0;
}
法二代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long LL;
const LL MOD = 998244353;
LL p[25],q[25],inv[25],ans;
LL POW(LL a,LL b){
LL res = 1LL;
while(b){
if(b&1){
res = res*a%MOD;
}
a = a*a%MOD;
b/=2;
}
return res;
}
int main(void){
int T;
scanf("%d",&T);
while(T--){
int m;
scanf("%d",&m);
ans = 1LL;
for(int i=0;i<m;i++){
scanf("%lld%lld",&p[i],&q[i]);
inv[i] = POW(p[i],MOD-2);
ans = ans*POW(p[i],q[i])%MOD;
}
for(int i=0;i<m;i++){
ans = ans*(q[i]*(p[i]-1)%MOD*inv[i]%MOD+1)%MOD;
}
printf("%lld\n",ans);
}
return 0;
}