D.冬はここにある(数学+カウント数)

タイトル

質問の意味:

    配列を考えると、答えの条件を満たすためにすべてのシーケンスの寄与を識別するために尋ねました。GCDシーケンスは、GCDは、*配列の長さに貢献し、1以上です。
     1 n 200000 , 1 a i 1000000 1≤N≤200000,1≤a_iを≤1000000

分析:

    探しはサブシーケンスではなく、サブ区間であるため、私たちは行うには、左の点を列挙することはできません。私たちは、これ以上の最大公約数の値とするので、その点に注意してください、そして各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;
}

公開された132元の記事 ウォンの賞賛6 ビュー7924

おすすめ

転載: blog.csdn.net/weixin_44316314/article/details/104884326