专栏文章
P2429 制杖题题解
P2429题解参与者 5已保存评论 5
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 5 条
- 当前快照
- 1 份
- 快照标识符
- @mkq95vhc
- 此快照首次捕获于
- 2026/01/23 10:19 上个月
- 此快照最后确认于
- 2026/01/23 10:19 上个月
设为中能被,为这个集合内所有数的和
初步思路为Ans=,但这样会有问题,比如样例中的p=3和5,若是使用这种方法,15的倍数会被计算2次。而且这只是两个质数,当变大时,看起来似乎很难处理。
这时候我想到了容斥定理(具体计算公式我就不打了qwq),观察公式发现其中奇数个集合的并集的符号都是,偶数个集合的并集的符号都是。于是我想到了深搜,即计算所有小于的能被组成的数(由题意可知其不含平方因子)
我已开始觉得这种做法可能会TLE。
然后我发现(即前几个质数的乘积)
也就是说被组成的数含p的因子个数其实最多只有9个,显然时间复杂度没有想象中的那么高。于是马上开搞。
Code:
CPP#include <bits/stdc++.h>
#define int long long
using namespace std;
int n,m;
int p[100001];
int a[201];//用a记录这个质数是否取过了
int ans;
void dfs(int x,int sum) {//x为取到第几个质数了,显然取了一个编号为n的质数不能再取一个编号为m(m<n)的质数,否则有可能会由部分乘积被重复计算多次
int p0=1;
for(int i=1; i<=n; i++) {//算出当前取出的这个数
if(a[i]==1) p0*=p[i];
}
if(p0>m) return ;
int t=m/p0;
// cout<<p0<<endl;
if(sum%2==1)ans=ans+((1+t)*t/2)%376544743*p0;//奇数个质数的乘积就相加,偶数个质数的乘积就相减
if(sum%2==0) ans=ans-((1+t)*t/2%376544743)*p0;
ans%=376544743;
for(int i=x+1; i<=n; i++) {
if(a[i]==0) {
a[i]=1;
dfs(i,sum+1);
a[i]=0;
}
}
}
signed main() {
cin>>n>>m;
for(int i=1; i<=n; i++) {
cin>>p[i];
}
for(int i=1; i<=n; i++) {
memset(a,0,sizeof(a));//每次记得清0
a[i]=1;
dfs(i,1);
}
cout<<ans<<endl;
return 0;
}
有段时间没写题解了,有些表述方面可能有问题,望指出
相关推荐
评论
共 5 条评论,欢迎与作者交流。
正在加载评论...