一次函数(好难的一次函数)

一次函数


(fx.c/cpp/pas)


【题目描述】


fqk 退役后开始补习文化课啦, 于是他打开了数学必修一开始复习
函数, 他回想起了一次函数都是 b kx x f   ) ( 的形式, 现在他给了你 n 个
一次函数


i i i
b x k x f   ) ( , 然后将给你 m 个操作, 操作将以如下格式给出:
M . 1 i k b ,把第 i 个函数改为 b kx x f i   ) ( 。
Q . 2 l r x ,询问 ))) ( (... (
1
x f f f
l r r 
mod 1000000007 的值。


【输入格式】


第一行两个整数 n , m ,代表一次函数的数量和操作的数量。
接下来 n 行,每行两个整数,表示
i
k ,
i
b 。
接下来 m 行,每行的格式为 M i k b 或 Q l r x 。


【输出格式】


对于每个操作 Q ,输出一行表示答案。


【输入样例】


5 5
4 2
3 6
5 7
2 6
7 5
Q 1 5 1
Q 3 3 2
M 3 10 6
Q 1 4 3
Q 3 4 4


【输出样例】


1825
17
978
98


【数据范围】


对于 % 30 的数据, 1000 ,  m n 。
对于 % 100 的数据, 1000000007 , , , 200000 ,   x b k m n 。


【时空限制】


对于每个测试点,时间限制为 s 2 ,空间限制为 MB 512 。

 

思路:

  刚开始先看数据范围(好习惯)

  发现这是个暴力过不了的题

  于是开始边推公式边码代码

  推了一个小时公式终于推了出来

  但是爆零了!

  因为这个题里有一个mod条件

  大于这个mod值就必须被mod

  但是我的公式里有用到除法

  所以就被整数不能被零除这种错误给RE了

  最后还是ylf大神讲的思路

  正解是线段树

  题目里的操作M和Q正符合线段树的单点修改和区间查询

  所以我开始着手写线段树

  线段树要维护两个值

  hyxzc告诉我要用数组比结构体要快

  但是我还是用的结构体

  在维护线段树的值得时候

  维护k和b

  具体是这样维护的

  k2*(k1*x+b1)+b2

  可以化成这种形式

  k2*k1*x+k2*b1+b2

  这样我们就可以得到新的值

  k3=k2*k1,b3=k2*b1+b2

  k3,b3就是一个小区间的值

  这样我们就可以推出l到r的k于b

 

  来,上代码:

#include<cmath>
#include<cstdio>
#include<iostream>

#define mod 1000000007

using namespace std;

struct node {
    long long int l,r,kl,b;
};
struct node tree[10000001],cur;

long long int n,m,jkl,ll,rr,dis;

char ch,ch1;

void qread(long long int &x)
{
    x=0,jkl=1;ch=getchar();
    while(ch>'9'||ch<'0'){if(ch=='-') jkl=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+(int)(ch-'0');ch=getchar();}
    x*=jkl;
}

void tree_up(long long int k)
{
    tree[k].kl=(tree[k<<1].kl*tree[k<<1|1].kl)%mod;
    tree[k].b=((tree[k<<1].b*tree[k<<1|1].kl)%mod+tree[k<<1|1].b)%mod;
}

void tree_build(long long int k,long long int l,long long int r)
{
    tree[k].l=l,tree[k].r=r;
    if(l==r)
    {
        qread(tree[k].kl),qread(tree[k].b);
        return ;
    }
    long long int mid=(l+r)>>1;
    tree_build(k<<1,l,mid),tree_build(k<<1|1,mid+1,r);
    tree_up(k);
}

void tree_change(long long int k,long long int to,long long int nk,long long int nb)
{
    if(tree[k].l==tree[k].r&&tree[k].l==to)
    {
        tree[k].kl=nk,tree[k].b=nb;
        return ;
    }
    long long int mid=(tree[k].l+tree[k].r)>>1;
    if(to<=mid) tree_change(k<<1,to,nk,nb);
    else tree_change(k<<1|1,to,nk,nb);
    tree_up(k);
}

struct node tree_sum(long long int k,long long int l,long long int r)
{
    if(l==tree[k].l&&r==tree[k].r) return tree[k];
    long long int mid=(tree[k].l+tree[k].r)>>1;
    if(l>mid) return tree_sum(k<<1|1,l,r);
    else if(r<=mid) return tree_sum(k<<1,l,r);
    else
    {
        struct node now1,now2;
        now1=tree_sum(k<<1,l,mid);
        now2=tree_sum(k<<1|1,mid+1,r);
        now1.b=((now2.kl*now1.b)%mod+now2.b)%mod;
        now1.kl=(now1.kl*now2.kl)%mod;
        return now1;
    }
}

int main()
{
    qread(n),qread(m);
    tree_build(1,1,n);
    for(long long int i=1;i<=m;i++)
    {
        //scanf("%c %lld%lld%lld",&ch1,&ll,&rr,&dis);
        scanf("%c ",&ch1);
        qread(ll),qread(rr),qread(dis);
        if(ch1=='M') tree_change(1,ll,rr,dis);
        else
        {
            cur=tree_sum(1,ll,rr);
            dis=((dis*cur.kl)%mod+cur.b)%mod;
            cout<<dis<<endl;
        }
    }
    return 0;
}

 

 

  附,祭奠我那逝去的公式=.=

  :

#include<cstdio>
#include<cstdlib>
#include<iostream>

#define mod 1000000007

using namespace std;

struct node {
    long long int k,b;
};
struct node function[2000002];

long long int n,m,jkl,l,r,dis,cur,kol;
long long int sumk[2000002],sumb[2000002],sumbb[2000002];

char ch,ch1;

bool ok=false;

void qread(long long int &x)
{
    x=0,jkl=1;ch=getchar();
    while(ch>'9'||ch<'0'){if(ch=='-') jkl=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+(int)(ch-'0');ch=getchar();}
    x*=jkl;
}

void change()
{
    for(long long int j=1;j<=n;j++)
    {
        sumk[j]=(sumk[j-1]*function[j].k)%mod;
        //sumb[j]=((sumb[i-1]*function[i].k)%mod+function[i].b)%mod;
    }
    for(long long int j=1;j<=n;j++)
    {
        sumb[j]=(((function[j].b*sumk[n])%mod)/sumk[j])%mod;
        sumbb[j]=sumbb[j-1]+sumb[j];
    }
    ok=false;
}

int main()
{
    sumk[0]=1;
    qread(n),qread(m);
    sumk[n+1]=1;
    for(long long int i=1;i<=n;i++)
    {
        qread(function[i].k),qread(function[i].b);
        sumk[i]=(sumk[i-1]*function[i].k)%mod;
        //sumb[i]=((sumb[i-1]*function[i].k)%mod+function[i].b)%mod;
        sumb[i]=function[i].b;
    }
    for(long long int i=1;i<=n;i++)
    {
        sumb[i]=(((sumb[i]*sumk[n])%mod)/sumk[i])%mod;
        sumbb[i]=sumbb[i-1]+sumb[i];
    }
    for(long long int i=1;i<=m;i++)
    {
        scanf("%c",&ch1),qread(l),qread(r),qread(dis);
        //cout<<l<<" "<<r<<" "<<dis<<" "<<endl;
        if(ch1=='M')
        {
            function[l].k=r,function[l].b=dis,ok=true;
            /*for(long long int j=1;j<=n;j++)
            {
                sumk[j]=(sumk[j-1]*function[j].k)%mod;
                //sumb[j]=((sumb[i-1]*function[i].k)%mod+function[i].b)%mod;
            }
            for(long long int j=1;j<=n;j++)
            {
                sumb[j]=(((function[j].b*sumk[n])%mod)/sumk[j])%mod;
                sumbb[j]=sumbb[j-1]+sumb[j];
            }*/
        }
        else
        {
            if(ok) change();
            cur=dis;
            cur=((cur*sumk[r]%mod)/sumk[l-1])%mod;
            //cout<<cur<<endl;
            //kol=(sumb[r]-sumb[l-1]);
            /*if(sumk[n]/sumk[r]==0){
                cout<<n<<" "<<r<<endl;
                cout<<sumk[n]<<" "<<sumk[r]<<endl;
                system("pause");
            }*/
            kol=((sumbb[r]-sumbb[l-1])/(sumk[n]/sumk[r]));
            //cout<<n<<" "<<r<<endl;
            //cout<<sumk[n]<<" "<<sumk[r]<<endl;
            //cout<<sumk[n]/sumk[r]<<endl<<(sumbb[r]-sumbb[l-1])<<endl<<kol<<endl;
            cur=(cur+kol)%mod;
            cout<<cur<<endl;
        }
    }
    return 0;
}

 

posted @ 2016-11-09 21:13  IIIIIIIIIU  阅读(738)  评论(0编辑  收藏  举报