【HDOJ 4768】 Flyer (等差数列+二分)
发。。超人? 。。翻译略过 反正是给小盆友发什么东西。。 然后发n次 每次规则是从A下标开始发 每C人发一个 发到B之前 即每次得到玩具的小朋友是A A+C A+2*C... A+K*C(A+K*C <= B)
问是否有得到奇数个玩具的小朋友 保证有的话只有一人 输出该小朋友编号和得到玩具数 没有输出-1
二分 所有组中最小编号为下界 最大B为上界 二分条件是所有组从A到mid(二分中点) 得到玩具的个数和为奇数时 则奇数小朋友在low~mid里 否则在mid~high里(有的话)
因为如果mid之前小朋友有一个得到奇数的话 之前所有小朋友得到玩具数一定为奇 否则为偶 (偶+偶得偶 偶+奇得奇数) 因为题目说了有的话只有一个奇数 如果有多个的话奇+奇得奇 就没法这么做了
还要注意的是上限2^31 爆int
代码如下:
#include
#define ll long long
using namespace std;
typedef struct Range Range;
struct Range
{
ll a,b,c;
};
Range rg[23333];
ll sum;
ll Binary(ll low,ll high,int n)
{
if(sum%2 == 0) return -1;
int i;
ll cnt,mid,id;
while(low <= high)
{
mid = (low+high)>>1;
for(cnt = i = 0; i < n; ++i)
{
if(mid >= rg[i].a)
cnt += (min(rg[i].b,mid)-rg[i].a)/rg[i].c+1;
}
if(cnt%2 == 1)
{
id = mid;
high = mid-1;
}
else
low = mid+1;
}
return id;
}
int main()
{
int i,n;
ll low,high,ans,cnt;
while(~scanf("%d",&n))
{
low = 1LL<<31;
high = 0;
sum = 0;
for(i = 0; i < n; ++i)
{
scanf("%I64d %I64d %I64d",&rg[i].a,&rg[i].b,&rg[i].c);
high = max(high,rg[i].b);
low = min(low,rg[i].a);
sum += (rg[i].b-rg[i].a)/rg[i].c+1;
}
ans = Binary(low,high,n);
if(ans == -1) puts("DC Qiang is unhappy.");
else
{
for(cnt = i = 0; i < n; ++i)
{
if(ans >= rg[i].a && ans <= rg[i].b && (ans-rg[i].a)%rg[i].c == 0) cnt++;
}
printf("%I64d %I64d\n",ans,cnt);
}
}
return 0;
}