Cerinta completa

Let denote an arithmetic progression (AP) with first term and common difference , i.e.  denotes an infinite . You are given APs => . Let denote the sequence obtained by multiplying these APs.

Multiplication of two sequences is defined as follows. Let the terms of the first sequence be , and terms of the second sequence be . The sequence obtained by multiplying these two sequences is

If are the terms of a sequence, then the terms of the first difference of this sequence are given by calculated as respectively. Similarly, the second difference is given by , and so on.

We say that the difference of a sequence is a constant if all the terms of the difference are equal.

Let be a sequence defined as =>
Similarly, is defined as => product of .

Task:
Can you find the smallest for which the difference of the sequence is a constant? You are also required to find this constant value.

You will be given many operations. Each operation is of one of the two forms:

1) 0 i j => 0 indicates a query . You are required to find the smallest for which the  difference of  is a constant. You should also output this constant value.

2) 1 i j v => 1 indicates an update . For all , we update .

Input Format
The first line of input contains a single integer , denoting the number of APs.
Each of the next lines consists of three integers .
The next line consists of a single integer , denoting the number of operations. Each of the next lines consist of one of the two operations mentioned above.  

Output Format
For each query, output a single line containing two space-separated integers and . is the smallest value for which the difference of the required sequence is a constant. is the value of this constant. Since might be large, output the value of modulo 1000003.

Note: will always be such that it fits into a signed 64-bit integer. All indices for query and update are 1-based. Do not take modulo 1000003 for .

Constraints



For updates of the form 1 i j v,
 

Sample Input

2  
1 2 1  
5 3 1  
3  
0 1 2  
1 1 1 1  
0 1 1  

Sample Output

2 12  
2 8  

Explanation

The first sequence given in the input is =>
The second sequence given in the input is =>

For the first query operation, we have to consider the product of these two sequences:
=>
=>
First difference is =>
Second difference is => This is a constant and hence the output is 2 12.

After the update operation 1 1 1 1, the first sequence becomes =>
i.e =>
For the second query, we consider only the first sequence =>
First difference is =>
Second difference is => This is a constant and hence the output is 2 8


Limbajul de programare folosit: cpp14

Cod:

#include <cstdio>
#include <iostream>
using std::swap;
using std::cout;
using std::endl;

typedef long long LL;
const LL Mod=1000003;
const int N=100001;
const LL INF=1LL<<62;

LL f[Mod+10];


LL power(LL base, LL k)
{
    LL res=1;
    while(k){
        if(k&1) res=(res*base)%Mod;
        base=(base*base)%Mod;
        k>>=1;
    }  
    return res;
}

struct Node{
    int l,r;//sum;
    LL K;
    LL sk;
    LL V;
    LL V2;
    LL s;
    Node *lc,*rc;
    LL getK()
    {
        return K+sk*(r-l+1LL);    
    }
    
    LL getV2()
    {
        return (power(V,s)*V2)%Mod;
        //return power(V,s);
    }
};

Node buf[200010];
Node* root;
int pt=0;


Node*  New()
{
    buf[pt].lc=buf[pt].rc=NULL;
    buf[pt].l =buf[pt].r =-INF;
    buf[pt].K=-1;
    buf[pt].V=-1;
    buf[pt].s=-1;
    return buf+pt++;
}

void build(Node* root, int l,int r)
{
    root->l=l;
    root->r=r;
    root->K=0;
    root->V=1;
    root->V2=1;
    root->s=0;
    root->sk=0;

    if(l==r)return;

    root->lc=New();
    root->rc=New();

    int mid=(l+r)/2;
    build(root->lc,l,mid);
    build(root->rc,mid+1,r);
}

void fresh(Node* root)
{
    root->K = root->lc->getK() + root->rc->getK();
    root->V = (root->lc->V*root->rc->V )%Mod;
    root->V2 = (root->lc->getV2()*root->rc->getV2())%Mod;
}

LL queryK(Node* root,int l, int r)
{
    if(root->l==l && root->r==r){
        return root->getK();
    }    
    int mid = (root->l+root->r)/2;
    if(l>mid){
        LL res=queryK(root->rc,l,r);
        return res+root->sk*(r-l+1LL);
    }
    else if(r<=mid){
        LL res=queryK(root->lc,l,r);
        return res+root->sk*(r-l+1LL);
    }
    else{
        LL a = queryK(root->lc,l,mid);
        LL b = queryK(root->rc,mid+1,r);
        return a+b+root->sk*(r-l+1LL);        
    }
    return -INF;
}

LL queryV(Node* root,int l, int r, int ac)
{
    //printf("root->l=%d root->r=%d root->s=%I64d root->v=%I64d root->k=%I64dn",
    //root->l,root->r,root->s,root->V,root->K);
    
    if(root->l==l && root->r==r){
        //return power(root->V,ac+root->s);
        LL res = root->getV2();
        return (res*power(root->V,ac))%Mod;
    }    
    int mid = (root->l+root->r)/2;
    if(l>mid){
        //LL res=queryV(root->rc,l,r);
        //return power(res,root->s+1);
        //return (res*root->getV())%Mod;
        
        return queryV(root->rc,l,r,ac+root->s);
    }
    else if(r<=mid){
        //LL res=queryV(root->lc,l,r);
        //return power(res,root->s+1);
        //return (res*root->getV())%Mod;
        
        return queryV(root->lc,l,r,ac+root->s);
    }
    else{
        LL a = queryV(root->lc,l,mid,ac+root->s);
        LL b = queryV(root->rc,mid+1,r,ac+root->s);
        LL res = (a*b)%Mod;
        //return power((a*b)%Mod,root->s+1);        
        //return (res*root->getV())%Mod;
        
        return res;
    }
    return -INF;
}


void add( Node* root, int l, int r, int delta)
{
    //printf("root->l=%d root->r=%d l=%d r=%d val=%dn",root->l,root->r,l,r,val);
    
    if(root->l==l && root->r==r){
        root->s += delta;
        root->sk += delta;
        return;
    }

    int mid = (root->l+root->r)/2;
    if(l>mid){
        add(root->rc,l,r,delta);
    }
    else if(r<=mid){
        add(root->lc,l,r,delta);
    }
    else{
        add(root->lc,l,mid,delta);
        add(root->rc,mid+1,r,delta);
    }
    fresh(root);
}

void update(Node* root,int l,int r,int d,int k)
{
    //printf("update, l=%d r=%d val=%dn",root->l,root->r,val);
    if(l!=r){
        puts("currently only update single element");
    }

    if(root->l==l && root->r==r){
        //printf("index=%d is updated, val=%dn",l,val);
        root->V=d;
        root->K=k;
        root->s=k;
        root->sk=0;
        return;
    }

    int mid = (root->l+root->r)/2;

    if(l>mid){
        //puts("should not execute");
        update(root->rc,l,r,d,k);
    }
    else if(r<=mid){
        update(root->lc,l,r,d,k);
    }
    else{
        //puts("should not execute");
        //add(root->lc,l,mid,val);
        update(root->rc,mid+1,r,d,k);
    }
    
    fresh(root);
}


void output(Node* p, int l, int r)
{
    if(p->l==l && p->r==r){
        if(l==r){
            printf("index=%d K=%I64d V=%I64dn",l,queryK(root,l,l),queryV(root,l,l,0));
        }
        else{
            output(p->lc,l,(l+r)/2);
            output(p->rc, (l+r)/2+1, r);    
        }
        return;
    }    
    int mid=(p->l+p->r)/2;
    if(l>mid){
        output(p->rc,l,r);    
    }
    else if(r<=mid){
        output(p->lc,l,r);        
    }
    else{
        output(p->lc,l,mid);
        output(p->rc,mid+1,r);    
    }
}

void Init()
{
    root=New();
    build(root,1,N);
    f[0]=1;
    for(int i=1;i<Mod;++i)
        f[i]=(i*f[i-1])%Mod;
}

int main()
{
    Init();
    /*
    output(root,1,10);
    update(root,2,2,0);
    add(root,3,N,2);
    puts("add(root,3,N,2)");
    output(root,1,10);
    
    update(root,1,1,0);
    add(root,2,N,1);
    
    puts("add(root,2,N,1)");
    output(root,1,10);
    */
    //return 0;
    char cmd[10];

    int n,q;
    scanf("%d",&n);
    for(int i=1;i<=n;++i){
        int a,d,p;
        scanf("%d%d%d",&a,&d,&p);
        update(root,i,i,d,p);        
    }
    
    scanf("%d",&q);
    while(q--){
        int c,a,b,delta;
        scanf("%d",&c);
        
        if(!c){
            scanf("%d%d",&a,&b);      
            LL r1 = queryK(root,a,b);
            LL r2 = queryV(root,a,b,0);
            //printf("K=%I64d V=%I64dn",r1,r2);
            r2 = r1<Mod ? (f[r1]*r2)%Mod : 0;
            
            cout<<r1<<" "<<r2<<endl;    
        }
        else{
            scanf("%d%d%d",&a,&b,&delta);  
            add(root,a,b,delta);
        }  

        //output(root,1,10);
    }


    return 0;
}

Scor obtinut: 1.0

Submission ID: 464653760

Link challenge: https://www.hackerrank.com/challenges/arithmetic-progressions/problem

Arithmetic Progressions