zhouruoheng
2024-11-19 17:27:02
dp 加容斥。
逐步推导,设
这样做是
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
#include <set>
using namespace std;
typedef long long ll;
const int N=2e5+5,mod=998244353,M=1e6+5;
int n;
int a[N];
int f[N];
int gcd(int x,int y)
{
return y ? gcd(y,x%y) : x;
}
vector<int> g[M],h[N];
set<int> v;
void solve()
{
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
f[1]=1;
for(int i=2;i<=n;i++)
for(int j=1;j<=i-1;j++)
if(gcd(a[i],a[j])!=1)
f[i]=(f[i]+f[j])%mod;
cout<<f[n]<<'\n';
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
#endif
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
solve();
return 0;
}
考虑优化,不难发现我们其实并不在意具体的
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
#include <set>
using namespace std;
typedef long long ll;
const int N=2e5+5,mod=998244353,M=1e6+5;
int n;
int a[N],f[N];
vector<int> g[M],h[N];
set<int> v;
void solve()
{
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
int x=a[1];
for(int j=2;1ll*j*j<=n;j++)
{
if(x%j==0)
{
g[j].push_back(1);
while(x%j==0) x/=j;
}
}
if(x>1) g[x].push_back(1);
f[1]=1;
for(int i=2;i<=n;i++)
{
int x=a[i];
for(int j=2;1ll*j*j<=x;j++)
{
if(x%j==0)
{
for(int k:g[j])
{
if(v.count(k)==0) f[i]=(f[i]+f[k])%mod;
v.insert(k);
}
g[j].push_back(i);
while(x%j==0) x/=j;
}
}
if(x>1)
{
for(int k:g[x])
{
if(v.count(k)==0) f[i]=(f[i]+f[k])%mod;
v.insert(k);
}
g[x].push_back(i);
}
v.clear();
}
cout<<f[n]<<'\n';
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
#endif
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
solve();
return 0;
}
但这样还是过不了。因为这最坏还是
然后不妨按质因数划分集合,设
考虑这样一组数据
这里就是
如何避免这样情况呢?用容斥原理。
将 g[a[i]]
中。比如 g[12]={2,3,6}
,这时候可以计算上面例子,
也就是说在每次更新 g[a[i]]
中的每个元素 g[a[i]]
中的每个元素
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
using namespace std;
typedef long long ll;
const int N=2e5+5,M=1e6+5,mod=998244353;
int n;
int a[N],b[M],f[N];
vector<int> g[M],h[M];
void divide1(int x,int id)
{
for(int i=2;1ll*i*i<=x;i++)
{
if(x%i==0)
{
h[id].push_back(i);
while(x%i==0) x/=i;
}
}
if(x>1) h[id].push_back(x);
}
void divide2(int x,int id)
{
x=1;
for(auto t:h[id]) x*=t;
for(int i=2;1ll*i*i<=x;i++)
{
if(x%i==0)
{
g[id].push_back(i);
if(x!=i) g[id].push_back(x/i);
}
}
if(x>1) g[id].push_back(x);
}
void solve()
{
cin>>n;
int mx=0;
for(int i=1;i<=n;i++) cin>>a[i],mx=max(mx,a[i]);
for(int i=2;i<=mx;i++) divide1(i,i),divide2(i,i);
f[1]=1;
for(int i=1;i<=n;i++)
{
for(auto x:g[a[i]])
{
if(h[x].size()&1) f[i]=(f[i]+b[x])%mod;
else f[i]=(f[i]+mod-b[x])%mod;
}
for(auto x:g[a[i]]) b[x]=(b[x]+f[i])%mod;
}
cout<<f[n]<<'\n';
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
#endif
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
solve();
return 0;
}