2016陕西省省赛 ACM Rui and her functions B 二分

Rui and her functions

发布时间: 2017年3月27日 15:45   最后更新: 2017年3月28日 12:43   时间限制: 10000ms   内存限制: 256M

Rui is magnificently gifted. Why does she not play with me tonight? Oh, she is obsessing

about  n  functions with  n  quartette of positive coefficients, denoted by  ai,bi,ci,di(1in)

respectively.

The i-th function fi is defined as  fi(x)=(ai×bxi+ci)moddi . She asked Doc to find the

smallest  xi  in  [1,m]  for each function such that  fi(xi)  achieves the minimum of  fi  in  [1,m] .

That is say:  fi(xi)=min{x[1,m]|fi(x)=mint[1,m]{fi(t)}} .

However n is large and Doc told her that possible  xi  for each function is unique (and Rui

is unique as well), and  x1x2x3xn  (and that is as amazing as Rui).

Now she needs to find  xi  by herself.

There are several test cases (no more than 64) and please process till EOF.
The first line in each case contains two integers  n  and  m 1n,m100000 . Each of the
following  n  lines contains four integers  ai,bi,ci,di  respectively, where  0<ai,bi,cidi109 .

For each test case, print first the identifier of the test case, then n lines follow. The  i -th
line contains the number  xi  for  i -th function  fi .

  复制
3 5
373911025 1525760443 652804587 1767005941
120055457 159868670 59429374 196292251
1200581 955324 141748 2705431
Case #1
1
2
4
总感觉这道题目描述的不好,或者是我一直没有理解好。这个题目说的是每个f函数,x在[1,m]区间上的取值,f(x)都是不同的

然后让你求出每个f(x)取得最小值情况下的x,这个题有点特殊,数据保证了x1<=x2<=...<=xn我觉得这个数据不是随机出的,而是故意满足了这个条件。

由于x的单调性,我们可以这样考虑,如果我们先求出了下标n/2对应的函数对应的x,那么对于所有下标小于n/2的f函数,就只需要考虑[1,x[n/2]]之内的数就可以了,因为这些函数

的最小值对应的x不可能大于x[n/2]了,这样的话,再判断左右两边的f函数对应的x时,要检索的范围就缩小了一半。

因此,上来就用二分

void solve(int lp,int rp,int l,int r)//左闭右开 
表示的是要求区间[lp,rp)内的函数对应的最小值,这些最小值的取值再[l,r)里面

那么我们先求pos = (lp+rp)/2位置的函数,假设求得了x的下标为under

那么下一次分治的时候,

左边的区间变成了[lp,pos) 定义域变成了[l,under+1)因为x之间可以相等

右边的函数下标区间变成了[pos+1,rp),定义域变成了[under,r)


注意!!!!!

快速幂不能一直使用,否则会TTTTTTT,555555555我在这地方T了20次!!!归根到底还是菜啊

解决方案是,在定义域内检索最小值的时候,先用快速幂求出第一项,然后递归得到以后的

#include <iostream>
#include <algorithm> 
#include <cstdio>
using namespace std;
typedef long long LL;
const int MAX = 100009;
const LL INF = 1e18;
LL a[MAX],b[MAX],c[MAX],d[MAX],ans[MAX];
int n,m;
LL mod_pow(LL x,LL n,LL mod)
{
	LL res = 1;
	while(n > 0)
	{
		if(n&1) res = res*x%mod;
		x = x*x%mod;
		n >>= 1;
	}
	return res;
}
/* 
LL calc(int x,int i)
{
	LL mod = d[i];
	return ((a[i]%mod*mod_pow(b[i],x,mod))%mod + c[i]%mod) % mod;
}
*/
void solve(int lp,int rp,int l,int r)//左闭右开 
{
	//返回中间位置
	if(lp >= rp) return ;
	int pos = (lp + rp) / 2;
	LL sm = INF;
	int under;
	int lb = l;
	int up = r;
	LL tmp = mod_pow(b[pos],lb,d[pos]);
	for(int i = lb;i < up;i++){
		if(i != lb) tmp = tmp*b[pos]%d[pos];
		LL cc = ((a[pos]%d[pos]*tmp)%d[pos] + c[pos]%d[pos]) % d[pos];
		if(sm > cc)
			sm = cc,under = i;
	}
  	ans[pos] = under;
	solve(lp,pos,l,under+1);
	solve(pos+1,rp,under,r);
}
main()
{
	int cas = 0;
	while(~scanf("%d%d",&n,&m))
	{
		for(int i = 0;i < n;i++)
			scanf("%lld%lld%lld%lld",a+i,b+i,c+i,d+i);
		LL sm = INF;
		printf("Case #%d\n",++cas);
		solve(0,n,1,m+1);
		for(int i = 0;i < n;i++) printf("%lld\n",ans[i]);
	} 
	return 0;
 } 
 /*
1 1
373911025 1525760443 652804587 1767005941
 */



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值