A HDU 5288 OO’s Sequence
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5288
题意:
定义f(l,r) :在l <= i <=r中,满足条件的个数。条件:对于i,所有的a[ i ] %a[ j ] != 0(其中l<=j<=r && i != j)
解题思路:
对于第i个数,如果能找到两个最靠近他的两个因子的位置,结果就很好求了
举个例子:
举个例子:
1 2 4 6 5 7 3 9
对于6这个数,它本身的位置是4,离他最近的左边的因子是2,第2个数,离他最近的右边的数是3,第7个数
那么6就能出现在(4-2)*(7-4) 就是6个集合里面
那么6就能出现在(4-2)*(7-4) 就是6个集合里面
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
using namespace std;
#define inf 100005
#define mod 1000000007
#define ll __int64
int a[inf];
int l[inf],r[inf];
int pre[inf],last[inf];
int main()
{
int n;
while(~scanf("%d",&n))
{
memset(pre,0,sizeof(pre));
memset(last,0,sizeof(last));
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
l[i]=1;
r[i]=n;
}
for(int i=1;i<=n;i++)
{
for(int j=a[i];j<=10000;j+=a[i])
{
if(pre[j]!=0 && r[pre[j]]==n) r[pre[j]]=i-1;
}
pre[a[i]]=i;
}
for(int i=n;i>=1;i--)
{
for(int j=a[i];j<=10000;j+=a[i])
{
if(last[j]!=0 && l[last[j]]==1) l[last[j]] = i+1;
}
last[a[i]] = i;
}
ll ans=0;
for(int i=1;i<=n;i++)
{
ans= (ans + (ll)(i-l[i]+1)*(r[i]-i+1)%mod)%mod;
}
printf("%I64d\n",ans);
}
return 0;
}
B HDU 5289 Assignment
题意:
n个人,每个人都有自己的能力值,给这堆人分组,使得组内的人两两之间的差值不超过K
解题思路:
这一题就相当于给你一串数,以每一个点为起点,算出它的最长序列,这个序列的最大值与最小值之差小于k,将每个序列的长度相加
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <math.h>
#include <algorithm>
using namespace std;
#define inf 100005
#define ll __int64
ll p[inf];
ll f[inf];
void init()
{
memset(f,0,sizeof(f));
for(int i=1;i<=inf;i++)
{
f[i] = f[i-1]+i;
}
}
int main()
{
init();
int t;
scanf("%d",&t);
while(t--)
{
int n;
ll k;
scanf("%d%I64d",&n,&k);
for(int i=1;i<=n;i++)
{
scanf("%I64d",&p[i]);
}
ll l=1;
ll minx ,maxn;
int s=2,r;
ll ans=0;
int flag=0,ff=0;
for(int i=1;i<=n;i++)
{
if(flag!=1)
{
if(i==1) minx = maxn = p[i];
else
{
if(p[i-1]!=minx && p[i-1]!=maxn)
{
l--;
s=r;
}
else
{
l=1;
s=i+1;
minx = maxn = p[i];
}
}
}
for(int j=s;j<=n;j++)
{
if(abs(p[j]-p[i])<k && abs(minx-p[j])<k && abs(maxn-p[j])<k)
{
minx = min(minx,p[j]);
maxn = max(maxn,p[j]);
l++;
if(j==n)
{
ans+=f[l];
ff=1;
break;
}
}
else
{
if(abs(p[j]-p[j-1])>=k)
{
ans+=f[l];
i = j-1;
s=j+1;
l=1;
minx = maxn = p[j];
flag=1;
if(i==n-1)
{
ans++;
ff=1;
}
}
else
{
flag=0;
ans+=l;
r=j;
}
break;
}
}
if(ff==1) break;
}
printf("%I64d\n",ans);
}
return 0;
}