題目傳送門
題意:
給你 個數的序列 ,問你 的子序列方案數。
數據範圍: 。
題解:
的質因子個數是奇數個,且沒有相同的質因子。
的質因子個數是偶數個,且沒有相同的質因子。
表示序列中 的倍數的個數。
表示 個數形成的非空集合的個數。
這就是莫比烏斯函數。
感受:
關鍵是分析本質不同的質因子。
代碼:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll ;
const int maxn = 1e5 + 5 ;
const ll mod = 1e9 + 7 ;
int n , cnt[maxn] , num[maxn] ;
bool vis[maxn] ;
int prime[maxn] ;
int mu[maxn] ;
void get_mu()
{
int up = 1e5 ;
int cnt = 0 ;
mu[1] = 1 ;
for(int i = 2 ; i <= up ; i ++)
{
if(!vis[i]) prime[++ cnt] = i , mu[i] = -1 ;
for(int j = 1 ; j <= cnt && prime[j] * i <= up ; j ++)
{
vis[prime[j] * i] = 1 ;
if(i % prime[j] == 0) break ;
else mu[i * prime[j]] = -mu[i] ;
}
}
}
void init()
{
int up = 1e5 ;
num[1] = n ;
for(int i = 2 ; i <= up ; i ++)
for(int j = i ; j <= up ; j += i)
num[i] += cnt[j] ;
}
ll qpow(ll a , ll b)
{
ll ans = 1 ;
a %= mod ;
while(b)
{
if(b & 1) ans = (ans * a) % mod ;
b >>= 1 , a = (a * a) % mod ;
}
return ans % mod ;
}
ll cal(int x)
{
ll ans = 0 ;
ans = qpow(2ll , ll(x)) ;
ans = (ans - 1 + mod) % mod ;
return ans ;
}
void solve()
{
int up = 1e5 ;
ll ans = cal(num[1]) ;
for(int i = 2 ; i <= 1e5 ; i ++)
{
ans += ll(mu[i]) * cal(num[i]) ;
ans %= mod ;
}
ans = (ans + mod) % mod ;
printf("%lld\n" , ans) ;
}
int main()
{
scanf("%d" , &n) ;
memset(cnt , 0 , sizeof(cnt)) ;
memset(num , 0 , sizeof(num)) ;
for(int i = 1 ; i <= n ; i ++)
{
int x ;
scanf("%d" , &x) ;
cnt[x] ++ ;
}
get_mu() ;
init() ;
solve() ;
return 0 ;
}