CF 475D CGCDSSQ 解题报告(DP)

来源:互联网 发布:游族网络 林奇个人兴趣 编辑:程序博客网 时间:2024/04/29 03:34

D. CGCDSSQ
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Given a sequence of integers a1, ..., an and q queries x1, ..., xq on it. For each query xi you have to count the number of pairs(l, r) such that 1 ≤ l ≤ r ≤ n and gcd(al, al + 1, ..., ar) = xi.

 is a greatest common divisor of v1, v2, ..., vn, that is equal to a largest positive integer that divides all vi.

Input

The first line of the input contains integer n, (1 ≤ n ≤ 105), denoting the length of the sequence. The next line contains nspace separated integers a1, ..., an, (1 ≤ ai ≤ 109).

The third line of the input contains integer q, (1 ≤ q ≤ 3 × 105), denoting the number of queries. Then follows q lines, each contain an integer xi, (1 ≤ xi ≤ 109).

Output

For each query print the result in a separate line.

Sample test(s)
input
32 6 3512346
output
12201
input
710 20 3 15 1000 60 16101234561020601000
output
14022202211

    解题报告: 昨晚CF的D题。当时想枚举起点,然后按照gcd的递减,二分出相同gcd时的最大终点,计算段gcd时用线段树。无奈超时……

    队友DP出来了,利用的性质是一样的。一段数长度越长,gcd越小,且严格单调递减。因为int类型在2^31以内,所以可以肯定一个数最多有31个gcd(每次减少至少一个素因子)。我们可以枚举终点,当前的gcd数可以由上一次gcd的结果递推出来。这样问题就解决了。

    代码如下(GNU C++0x 提交):

#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#include <cmath>#include <queue>#include <vector>#include <map>#include <set>#include <string>#include <iomanip>#include <cassert>using namespace std;#pragma comment(linker, "/STACK:1024000000,1024000000")#define ff(i, n) for(int i=0;i<(n);i++)#define fff(i, n, m) for(int i=(n);i<=(m);i++)#define dff(i, n, m) for(int i=(n);i>=(m);i--)#define travel(e, u) for(int e = u, v = vv[u]; e; e = nxt[e], v = vv[e])#define bit(n) (1LL<<(n))#define And(a, b) ((a) & (b))#define Or(a, b) ((a) | (b))#define Xor(a, b) ((a) ^ (b))#define clr(a, b) memset((a), b, sizeof(a))typedef long long LL;typedef unsigned long long ULL;void work();int main(){#ifdef ACM    freopen("in.txt", "r", stdin);#endif // ACM    work();    return 0;}void scanf(int & x, char ch = 0){    while((ch=getchar()) < '0' || ch > '9');    x = ch - '0';    while((ch=getchar()) >= '0' && ch <= '9') x = x * 10 + ch - '0';}/***************************************************************************************/int gcd(int a, int b){    if(a&&b) while(a>b?a=a%b:b=b%a);    return a+b;}int a[111111];int q[333333];void work(){    int n, m;    while(scanf("%d", &n) == 1)    {        fff(i, 1, n) scanf(a[i]);        int m;        scanf("%d", &m);        ff(i, m) scanf(q[i]);        map<int, LL> ans;        map<int, int> dp[2];        int now = 0, pre = 1;        fff(i, 1, n)        {            swap(now, pre);            dp[now].clear();            dp[now][a[i]] = 1;            for(auto it : dp[pre])                dp[now][gcd(a[i], it.first)] += it.second;            for(auto it : dp[now])                ans[it.first] += it.second;        }        ff(i, m) if(ans.count(q[i]))            printf("%I64d\n", ans[q[i]]);        else            puts("0");    }}

0 0
原创粉丝点击