2016陕西省赛 Rui and her functions

2016陕西省赛 Rui and her functions

题目链接:http://oj.xjtuacm.com/contest/4/problem/35/

题目大意:每组数据给定$n$和$m$,定义$f_i(x)=(a_ib_i^{x_i}+c_i)\%d_i$,数据满足$x_i$不严格递增,问对于每个$f_i(x)$取最小值的时候,$x_i$是多少.

分治

注意到$x_i$不严格递增,直接暴力的话最差复杂度为$O(m^2)$,极端数据为$x_0=x_1=...=x_{n-1}=1$.

为了避免这种情况,采取分治策略:先计算$x_{mid}$,使得$mid$左边部分有了较低的上界,复杂度大大降低.

代码如下:

 1 #include <cstdio>
 2 #define N 100005
 3 using namespace std;
 4 typedef long long ll;
 5 ll n,m,x,T,a[N],b[N],c[N],d[N],ans[N];
 6 ll mul(ll a,ll b,ll p){return (a*b)%p;}
 7 ll add(ll a,ll b,ll p){return (a+b)%p;}
 8 ll pow(ll a,ll n,ll p){
 9     ll r=1;
10     while(n){
11         if(n&1)r=mul(r,a,p);
12         a=mul(a,a,p);
13         n>>=1;
14     }
15     return r;
16 }
17 ll getx(ll a,ll b,ll c,ll d,ll l,ll r){
18     ll x=l;
19     ll temp=mul(a,pow(b,x,d),d);
20     ll minn=add(temp,c,d);
21     for(ll i=x+1;i<=r;++i){
22         if(minn==0)break;
23         temp=mul(temp,b,d);
24         if(add(temp,c,d)<minn){
25             minn=add(temp,c,d);
26             x=i;
27         }
28     }
29     return x;
30 }
31 void solve(ll il,ll ir,ll xl,ll xr){
32     if(il>ir)return;
33     ll mid=(il+ir)/2;
34     ans[mid]=getx(a[mid],b[mid],c[mid],d[mid],xl,xr);
35     solve(il,mid-1,xl,ans[mid]);
36     solve(mid+1,ir,ans[mid],xr);
37 }
38 int main(void){
39     while(~scanf("%lld%lld",&n,&m)){
40         T++;
41         for(int i=0;i<n;++i)
42             scanf("%lld%lld%lld%lld",&a[i],&b[i],&c[i],&d[i]);
43         solve(0,n-1,1,m);
44         printf("Case #%lld\n",T);
45         for(int i=0;i<n;++i)
46             printf("%lld\n",ans[i]);
47     }
48 }

 

posted @ 2017-05-11 15:24  barriery  阅读(241)  评论(0编辑  收藏  举报