您的位置:首页 > 其它

HDU 4578——Transformation

2017-08-18 10:03 127 查看

Transformation

Time Limit: 15000/8000 MS (Java/Others)    Memory Limit: 65535/65536 K (Java/Others)

Total Submission(s): 5927    Accepted Submission(s): 1472


[align=left]Problem Description[/align]
Yuanfang is puzzled with the question below:

There are n integers, a1, a2, …, an. The initial values of them are 0. There are four kinds of operations.

Operation 1: Add c to each number between ax and ay inclusive. In other words, do transformation ak<---ak+c, k = x,x+1,…,y.

Operation 2: Multiply c to each number between ax and ay inclusive. In other words, do transformation ak<---ak×c, k = x,x+1,…,y.

Operation 3: Change the numbers between ax and ay to c, inclusive. In other words, do transformation ak<---c, k = x,x+1,…,y.

Operation 4: Get the sum of p power among the numbers between ax and ay inclusive. In other words, get the result of axp+ax+1p+…+ayp.

Yuanfang has no idea of how to do it. So he wants to ask you to help him.

 

[align=left]Input[/align]
There are no more than 10 test cases.

For each case, the first line contains two numbers n and m, meaning that there are n integers and m operations. 1 <= n, m <= 100,000.

Each the following m lines contains an operation. Operation 1 to 3 is in this format: "1 x y c" or "2 x y c" or "3 x y c". Operation 4 is in this format: "4 x y p". (1 <= x <= y <= n, 1 <= c <= 10,000, 1 <= p <= 3)

The input ends with 0 0.

 

[align=left]Output[/align]
For each operation 4, output a single integer in one line representing the result. The answer may be quite large. You just need to calculate the remainder of the answer when divided by 10007.
 

[align=left]Sample Input[/align]

5 5
3 3 5 7
1 2 4 4
4 1 5 2
2 2 5 8
4 3 5 3
0 0

 

[align=left]Sample Output[/align]

307
7489

 

[align=left]Source[/align]
2013ACM-ICPC杭州赛区全国邀请赛

题意:
n个数初始为0,m个操作
操作分4种:
1 x y c x到y的所有数加c
2 x y c x到y的所有数乘c
3 x y c x到y的所有数变成c
4 x y p 求x到y的所有数的p次方的和 (1<=p<=3)

分析:
我们假设x到y的和为a,,x到y的平方的和为b,x到y的次方的和为d那么:
操作1过后 d=d+3*c*b+3*c*c*a+c*c*c*(y-x+1)     通过两个数的次方和推导:(x1+c)^3+(x2+c)^3=x1^3+x2^3+3*c*(x1^2+x2^2)+3*c*c*(x1+x2)+c^3*2
                    b=b+2*c*a+c*c*(y-x+1)         通过两个数的平方和推导   (x1+c)^2+(x2+c)^2=x1^2+x2^2+2*c*(x1+x2)+c^2*2
                    a=a+c*(y-x+1) 
ps:因为d的推导要用到a,b   b的推导要用到a所以每一次需要先算次方,再算平方,最后算普通和
操作2过后 a=a*c
                   b=b*c*c
                   d=d*c*c*c
操作3过后 a=c*(y-x+1)
                   b=c*c*(y-x+1)
                   d=c*c*c*(y-x+1)

可以看到,普通和,平方和,次方和的变化都与变化之前的三种和有关系,所以只存普通和会给求平方和与次方和造成不方便,所以我们把3个值一起存,一起更新。
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<vector>
#include<cmath>
#define INF 0x3f3f3f3f
#define EXP 0.00000001
#define MOD 10007
#define MAXN 100005
#define ltree 2*id,ll,mid
#define rtree 2*id+1,mid+1,rr
#define FO(i,n,m) for(int i=n;i<=m;++i)
#define mem(a) memset(a,0,sizeof(a))
typedef long long LL;

using namespace std;

int n,m;
int add[4*MAXN];
int mul[4*MAXN];
int ch[4*MAXN];
int tree1[4*MAXN],tree2[4*MAXN],tree3[4*MAXN];

void Pushup(int id)
{
tree1[id]=(tree1[2*id]+tree1[2*id+1])%MOD;
tree2[id]=(tree2[2*id]+tree2[2*id+1])%MOD;
tree3[id]=(tree3[2*id]+tree3[2*id+1])%MOD;
}

void Pushdown(int id,int ll,int rr)
{
int llen=(ll+rr)/2-ll+1;
int rlen=rr-(ll+rr)/2;
int lt=2*id,rt=2*id+1;
if(ch[id])
{
ch[lt]=ch[rt]=ch[id];
add[lt]=add[rt]=0;
mul[lt]=mul[rt]=1;
tree1[lt]=ch[id]*llen%MOD;
tree2[lt]=ch[id]*ch[id]%MOD*llen%MOD;
tree3[lt]=ch[id]*ch[id]%MOD*ch[id]%MOD*llen%MOD;
tree1[rt]=ch[id]*rlen%MOD;
tree2[rt]=ch[id]*ch[id]%MOD*rlen%MOD;
tree3[rt]=ch[id]*ch[id]%MOD*ch[id]%MOD*rlen%MOD;
ch[id]=0;
}
if(mul[id]!=1)
{
mul[lt]=mul[lt]*mul[id]%MOD;
mul[rt]=mul[rt]*mul[id]%MOD;
add[lt]=add[lt]*mul[id]%MOD;
add[rt]=add[rt]*mul[id]%MOD;
tree1[lt]=tree1[lt]*mul[id]%MOD;
tree2[lt]=tree2[lt]*mul[id]%MOD*mul[id]%MOD;
tree3[lt]=tree3[lt]*mul[id]%MOD*mul[id]%MOD*mul[id]%MOD;
tree1[rt]=tree1[rt]*mul[id]%MOD;
tree2[rt]=tree2[rt]*mul[id]%MOD*mul[id]%MOD;
tree3[rt]=tree3[rt]*mul[id]%MOD*mul[id]%MOD*mul[id]%MOD;
mul[id]=1;
}
if(add[id])
{
add[lt]=(add[lt]+add[id])%MOD;
add[rt]=(add[rt]+add[id])%MOD;
tree3[lt]=(tree3[lt]+3*add[id]*tree2[lt]%MOD+3*add[id]*add[id]%MOD*tree1[lt]%MOD+add[id]*add[id]%MOD*add[id]%MOD*llen%MOD)%MOD;
tree2[lt]=(tree2[lt]+2*add[id]*tree1[lt]%MOD+add[id]*add[id]%MOD*llen%MOD)%MOD;
tree1[lt]=(tree1[lt]+add[id]*llen%MOD)%MOD;
tree3[rt]=(tree3[rt]+3*add[id]*tree2[rt]%MOD+3*add[id]*add[id]%MOD*tree1[rt]%MOD+add[id]*add[id]%MOD*add[id]%MOD*rlen%MOD)%MOD;
tree2[rt]=(tree2[rt]+2*add[id]*tree1[rt]%MOD+add[id]*add[id]%MOD*rlen%MOD)%MOD;
tree1[rt]=(tree1[rt]+add[id]*rlen%MOD)%MOD;
add[id]=0;
}
}

void Build(int id,int ll,int rr)
{
add[id]=0;
mul[id]=1;
ch[id]=0;
if(ll==rr)
{
tree1[id]=0;
tree2[id]=0;
tree3[id]=0;
return;
}
int mid=(ll+rr)/2;
Build(ltree);
Build(rtree);
Pushup(id);
}

void Update(int id,int ll,int rr,int x,int y,int op,int c)
{
if(x<=ll&&rr<=y)
{
if(op==1)
{
add[id]=(add[id]+c)%MOD;
tree3[id]=(tree3[id]+3*c*tree2[id]%MOD+3*c*c%MOD*tree1[id]%MOD+c*c%MOD*c%MOD*(rr-ll+1)%MOD)%MOD;
tree2[id]=(tree2[id]+2*c*tree1[id]%MOD+c*c%MOD*(rr-ll+1)%MOD)%MOD;
tree1[id]=(tree1[id]+c*(rr-ll+1)%MOD)%MOD;
return;
}
if(op==2)
{
mul[id]=mul[id]*c%MOD;
add[id]=add[id]*c%MOD;
tree1[id]=tree1[id]*c%MOD;
tree2[id]=tree2[id]*c%MOD*c%MOD;
tree3[id]=tree3[id]*c%MOD*c%MOD*c%MOD;
return;
}
if(op==3)
{
add[id]=0;
mul[id]=1;
ch[id]=c;
tree1[id]=c*(rr-ll+1)%MOD;
tree2[id]=c*c%MOD*(rr-ll+1)%MOD;
tree3[id]=c*c%MOD*c%MOD*(rr-ll+1)%MOD;
return;
}
}
Pushdown(id,ll,rr);
int mid=(ll+rr)/2;
if(y<=mid)
Update(ltree,x,y,op,c);
else if(x>mid)
Update(rtree,x,y,op,c);
else
{
Update(ltree,x,mid,op,c);
Update(rtree,mid+1,y,op,c);
}
Pushup(id);
}

int Query(int id,int ll,int rr,int x,int y,int pow)
{
if(x<=ll&&rr<=y)
{
if(pow==1)
return tree1[id];
if(pow==2)
return tree2[id];
if(pow==3)
return tree3[id];
}
Pushdown(id,ll,rr);
int mid=(ll+rr)/2;
if(y<=mid)
return Query(ltree,x,y,pow);
else if(x>mid)
return Query(rtree,x,y,pow);
else
return (Query(ltree,x,mid,pow)+Query(rtree,mid+1,y,pow))%MOD;
}

int main()
{
while(~scanf("%d%d",&n,&m))
{
if(n==0&&m==0)
break;
Build(1,1,n);
while(m--)
{
int op,x,y,c;
scanf("%d%d%d
a2e0
%d",&op,&x,&y,&c);
if(op==4)
printf("%d\n",Query(1,1,n,x,y,c));
else
Update(1,1,n,x,y,op,c);
}
}
return 0;
}


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: