タイトル
質問の意味:
配列を考えると、答えの条件を満たすためにすべてのシーケンスの寄与を識別するために尋ねました。GCDシーケンスは、GCDは、*配列の長さに貢献し、1以上です。
分析:
探しはサブシーケンスではなく、サブ区間であるため、私たちは行うには、左の点を列挙することはできません。私たちは、これ以上の最大公約数の値とするので、その点に注意してください、そして各GCDのために、それはそれだけの倍数によって生成されます。したがって、我々は、それがの倍数を生成することで、GCDの列挙の値は、その値を検討してください。それの倍数を計算した後、多くの削除など多数。
その後、貢献。1 C [N-] [1] +2 C [N-] [2] + ... N- C [N-] [N-] = N- GCDの最終値によって、次に2 ^(N - 1)。しかし、我々はすべてのGCDを取り出した要素の、それがなければなりません考慮していません我々は、これらの状況を取り除くために持っているので、それは、複数のかもしれません。あなたはfの値を引いその倍数F [i]のを計算することができますので、その後、我々は降順列挙し、[I] Fを維持することは、私は(私を掛けない)GCDの寄与を表しています。
#include <iostream>
using namespace std;
typedef long long ll;
ll mod = 1e9 + 7;
const int N = 1e6;
ll cnt[N+5],f[N+5],d[N+5];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int n;
cin >> n;
d[0] = 1;
for (int i = 1; i <= n; i++)
{
d[i] = d[i-1] * 2 % mod;
}
for (int i = 1; i <= n; i++)
{
int x;
cin >> x;
cnt[x] ++;
}
ll ans = 0;
for (int i = N; i > 1; i--)
{
ll x = 0;
for (int j = i; j <= N; j += i )
{
x += cnt[j];
}
if( x )
{
f[i] = x * d[x-1] % mod;
for (int j = i + i; j <= N; j += i )
{
f[i] = ( f[i] - f[j] + mod ) % mod;
}
ans += (ll)i * f[i];
ans %= mod;
}
}
cout << ans << '\n';
return 0;
}