您的位置:首页 > 产品设计 > UI/UE

【多校第一场】【筛法改】HDU 5288 OO’s Sequence

2015-07-22 14:49 399 查看
这道题的数据范围需要让我们有些反应才是,虽然n的组数是1e5的大小,但是数字的范围是1e4。

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5288

思路是找到每一个元素的左端首个因数的位置和右端因数的位置,这是显而易见的。但是这题的问题却不是在这里,而是在于如何操作。学长介绍的方法是将他们从小到大排列,然后去寻找当前值的倍数。。。有点说不太清不过对着代码模拟一遍一个就好,注释才是正文系列。

记住,long long不要乱开,sort时记得你的数组是从哪开始的。(因为这些而WA了一天TAT)。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#define LL long long
using namespace std;

struct n
{
int num;
int id;
}num[1000100];
LL ans;
const int mod=1e9+7;
vector <int>lr[10002];

bool cmp(n a,n b)
{
return a.num<b.num;
}

int main()
{
int n;
while(~scanf("%d",&n))
{
for(int i=0;i<=10001;i++)
lr[i].clear();
ans=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&num[i].num);
num[i].id=i;
}

sort(num+1,num+n+1,cmp);

int k=1;
for(int i=1;i<=n;i++)
{
for(int j=num[i].num;j<=10000;j+=num[i].num)
{
lr[j].push_back(num[i].id);
}
if(i!=n && num[i].num==num[i+1].num) continue;

while(k<=i)
{
int l=0,r=n+1;
for(int j=0;j<lr[num[k].num].size();j++)
{
if(lr[num[k].num][j]<num[k].id && lr[num[k].num][j]>l)
{
l=lr[num[k].num][j];
}
else if(lr[num[k].num][j]>num[k].id && lr[num[k].num][j]<r)
{
r=lr[num[k].num][j];
}
}
ans=(ans+(num[k].id-l)*(r-num[k].id))%mod;
k++;
//                cout<<l<<" "<<r<<" "<<ans<<endl;
//                for(int i=1;i<=n;i++)
//                {
//                    printf("%d  |",lr[i].size());
//                    for(int j=0;j<lr[i].size();j++) printf(" %d",lr[i][j]);
//                    printf("\n");
//                }
}
}

//        for(int i=1;i<=n;i++)
//        {
//            printf("%d  |",lr[i].size());
//            for(int j=0;j<lr[i].size();j++) printf(" %d",lr[i][j]);
//            printf("\n");
//        }

printf("%lld\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: