2015 Multi-University Training Contest 1记录

1001 OO’s Sequence

分析:

对于例子,能够得到,我们要求的是(1,1)(1,2)(1,3)(1,4)(1,5)(2,2)(2,3)(2,4)(2,5)(3,3)(3,4)(3,5)(4,4)(4,5)(5,5)这些范围内满足题目中所给的要求的i的个数。所以能够将两个求和符号转换为考虑原来ai序列中每个ai对于结果的贡献。

对于题目,刚好能够发现,我们仅仅须要对于每个ai求离它左右近期的因子就能够了。这样两个因子之间范围内每个i都是满足题目要求。

然后考虑求解ai因子的策略。假设对于每个ai都是每次左右分别搜索,那么一定会超时的。所以我们採取一个预处理,这里是学长教我的,方法非常巧妙。自己无法总结出来,所以还是看看代码里面怎么求的就好了。

还有。那几个10w的数组必须开在全局变量中,不然会爆栈。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int mod=1e9+7;
int a[100000+5],r[100000+5],l[100000+5],vis[100000+5];
int main()
{
    int i,j,ans,n;
    while(~scanf("%d",&n))
    {
        if(n==0) break;
        for(i=1;i<=n;i++)
            scanf("%d",&a[i]);
        memset(l,0,sizeof(l));
        memset(vis,0,sizeof(vis));
        for(i=0;i<=n;i++) r[i]=n+1;

        for(i=1;i<=n;i++)
        {
            for(j=1;j*j<=a[i];j++)
            {
                if(a[i]%j!=0) continue;
                if(vis[j]>l[i]&&vis[j]<i) l[i]=vis[j];
                if(vis[a[i]/j]>l[i]&&vis[a[i]/j]<i) l[i]=vis[a[i]/j];
            }
            vis[a[i]]=i;
        }
        memset(vis,0,sizeof(vis));
        for(i=n;i>=1;i--)
        {
            for(j=1;j*j<=a[i];j++)
            {
                if(a[i]%j!=0) continue;
                if(vis[j]<r[i]&&vis[j]>i) r[i]=vis[j];
                if(vis[a[i]/j]<r[i]&&vis[a[i]/j]>i) r[i]=vis[a[i]/j];
            }
            vis[a[i]]=i;
        }

        for(ans=0,i=1;i<=n;i++)
        {
            ans+=(r[i]-i)*(i-l[i]);
            ans%=mod;
        }
        printf("%d
",ans%mod);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/cxchanpin/p/7275407.html