[2016陕西省赛B] Rui and her functions

2016陕西省赛B
给定n个函数,其中 fi(x)=(aibxi+ci)moddi
求对于每个函数最小的 x ,使得 fi 取到最小值
答案保证递增
其中 x [1,m] 中, n,m<1e5 , a,b,c,d<1e9


所以可以整体二分一下
由于答案已经保证递增了,所以就很简单
其实赛上想到了类似做法,但由于答案非严格递增
所以担心出现答案全相等的情况,把这种解法卡成 (nm)
后来赛后想了想,全相等的情况几乎不可能发生
因为随机数据的话,要搞出另一组数据答案等于某个值的概率是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;
}

你可能感兴趣的:(分治)