2016陕西省赛B
给定n个函数,其中 fi(x)=(ai∗bxi+ci)moddi
求对于每个函数最小的 x ,使得 fi 取到最小值
答案保证递增
其中 x 在 [1,m] 中, n,m<1e5 , a,b,c,d<1e9
所以可以整体二分一下
由于答案已经保证递增了,所以就很简单
其实赛上想到了类似做法,但由于答案非严格递增
所以担心出现答案全相等的情况,把这种解法卡成 (n∗m) 的
后来赛后想了想,全相等的情况几乎不可能发生
因为随机数据的话,要搞出另一组数据答案等于某个值的概率是1/m
搞出 n组的概率就是 1/(n*m),几乎不可能
#pragma comment(linker, "/STACK:102400000,102400000")
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef pair<int,int> Pii;
typedef long long LL;
typedef unsigned long long ULL;
typedef double DBL;
typedef long double LDBL;
#define MST(a,b) memset(a,b,sizeof(a))
#define CLR(a) MST(a,0)
#define SQR(a) ((a)*(a))
#define PCUT puts("\n----------")
#define PRI(x) cout << #x << ":" << x << endl;
const int maxn=1e5+10, INF=0x3f3f3f3f;
int N,M;
int A[maxn], B[maxn], C[maxn], D[maxn];
int ans[maxn];
int Pow(int,int,int);
void solve(int,int,int,int);
int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
#endif
int ck=0;
while(~scanf("%d%d", &N, &M))
{
for(int i=1; i<=N; i++) scanf("%d%d%d%d", &A[i], &B[i], &C[i], &D[i]);
solve(1,N,1,M);
printf("Case #%d\n", ++ck);
for(int i=1; i<=N; i++) printf("%d\n", ans[i]);
}
return 0;
}
void solve(int l, int r, int vl, int vr)
{
if(rreturn;
int mid = (l+r)>>1;
int val = Pow(B[mid], vl-1, D[mid]);
ans[mid] = vl-1;
Pii res = {INF, ans[mid]};
for(int i=vl; i<=vr; i++)
{
val = 1LL*val*B[mid]%D[mid];
res = min(res, {(1LL*A[mid]*val+C[mid])%D[mid], i});
}
ans[mid] = res.second;
solve(l, mid-1, vl, ans[mid]);
solve(mid+1, r, ans[mid], vr);
}
int Pow(int x, int n, int p)
{
int res=1;
while(n)
{
if(n&1) res = 1LL*res*x%p;
x = 1LL*x*x%p;
n>>=1;
}
return res;
}