HPU-1008-Mod

来源:互联网 发布:linux启动tomcat报错 编辑:程序博客网 时间:2024/05/18 03:33

ACM模版

描述

描述
描述

题解

这是一道十分有意思的问题,刚拿到手时第一感觉就是找周期性,可是总感觉缺点啥,不知道怎么去实现,然后看到了郑大的学长方寸的代码,顿悟,真是一个十分巧妙的处理手法。

首先,我们知道,这个序列中并不是所有的a[i]都对最后的结果能产生贡献,所以第一我们要删选出来能产生贡献的序列,这个序列a_[]一定是递减的,然后我们从最小的开始枚举构造周期性,不断用较大的a_[]来修正周期性,直到最后得到一个周期性数组vis[],这里true代表一个周期结束,要重新开始周期,周期的开始始终是vis[1],false代表渐变,对应的f[i]=f[i-1]+1,这里需要注意的是vis[]是一个严格的周期性数组,而f[]虽然存在周期性,却不是严格的,因为f[]的第一个周期的开始是val(代码中已给出),而剩下的周期的起点则是0。

总而言之,思路很好,代码实现起来不是太容易想,Orz~~~

代码

#include <iostream>#include <cstdio>#include <cstring>#define ll long longusing namespace std;const int MAXN = 2000;const int MAXA = 100000;ll mlop;ll a[MAXN];ll a_[MAXN];ll f[MAXA];ll sum[MAXA];bool vis[MAXA];int cnt;int N, Q;void init(){    memset(sum, 0, sizeof(sum));    memset(vis, 0, sizeof(vis));    cnt = 1;    mlop = MAXA + 1;    a_[0] = mlop;    //  获取产生贡献的a[i]存入a_[j]    for (int i = 0; i < N; i++)    {        if (mlop > a[i])        {            a_[cnt++] = a[i];            mlop = a[i];        }    }    mlop = a_[cnt - 1];    for (int i = cnt - 2; i >= 0; i--)    {        ll j;        vis[mlop] = true;        //  周期性,ture表示返回周期开始,false表示渐变(上一个+1)        //  周期始终从vis[1]开始        for (j = mlop + 1; j + mlop - 1 <= a_[i]; j += mlop)        {            memcpy(&vis[j], &vis[1], sizeof(bool) * mlop);        }        if (j < a_[i])        {            memcpy(&vis[j], &vis[1], sizeof(bool) * (a_[i] - j + 1));        }        mlop = a_[i];    }    ll val = 1;    //  获取周期起点值    for (int i = 1; i < cnt; i++)    {        val %= a_[i];    }    f[1] = val;    sum[1] = f[1];    for (int i = 2; i <= MAXA; i++)    {        f[i] = f[i - 1] + 1;        if (vis[i])        {            f[i] = 0;        }        sum[i] = sum[i - 1] + f[i];    }}int main(){    int T;    scanf("%d", &T);    while (T--)    {        scanf("%d", &N);        for (int i = 0; i < N; i++)        {            scanf("%lld", &a[i]);        }        init();        scanf("%d", &Q);        while (Q--)        {            ll l, r;            scanf("%lld%lld", &l, &r);            printf("%lld\n", sum[r] - sum[l - 1]);        }    }    return 0;}
0 0
原创粉丝点击