HDU 5239 Doom 线段树+找规律
2016-05-20 21:28
387 查看
import java.math.BigInteger; import java.util.Scanner; public class Main { public static void main(String args[]){ //Scanner cin=new Scanner(System.in); BigInteger a=BigInteger.valueOf(5); BigInteger d = BigInteger.valueOf((long) (Math.pow(2, 63)-Math.pow(2,31))); for(int i=1;i<=19;i++) { for(int j=1;j<=i;j++) { a=a.multiply(a); a=a.mod(d); System.out.println(a); } } } }
给出n个数和一个初始值为0的答案。每次操作给出一个区间[l,r],把区间所有的数加到答案中,之后把区间的每个数都平方。每次操作都需要输出答案
mod=9223372034707292160
这道题在做的时候没敢去做,主要是怕超时因为每次更新是很费时间的,但是后来看看题解发现是有规律
a=(a*a)%mod 经过有限次运算之后就可以的到一个不变的值用来防止超时
可以用java 打表看出来。
思路:这道题用线段树维护求和 ,
今后遇到比较大的数时,比较难算的运算时,可以考虑是否可以通过
1.循环节
2.经过几轮之后就不改变的
等特性来减少时间
#include<bits/stdc++.h> #define INF 0x3f3f3f3f #define bug puts("********************") #define LL unsigned long long #define mod 9223372034707292160 using namespace std; LL val[100010*4]; LL sum[100010*4]; int cnt[100010*4]; LL quick_add(LL x,LL y) { LL ans=0; while(y) { if(y&1) { ans=(ans+x)%mod; } y>>=1; x=(x+x)%mod; } return ans; } LL push_up(int ind) { sum[ind]=(sum[ind<<1]+sum[ind<<1|1])%mod; cnt[ind]=min(cnt[ind<<1],cnt[ind<<1|1]); } void Build(int l,int r,int ind) { if(l==r) { sum[ind]=val[r]; ///注意val[]下标为r或l cnt[ind]=0; return ; } int mid=(l+r)>>1; Build(l,mid,ind<<1); Build(mid+1,r,ind<<1|1); push_up(ind); } LL query(int L,int R,int l,int r,int ind) { if(l<=L&&r>=R) return sum[ind]; LL S=0; int mid=(L+R)>>1; if(l<=mid) S+=query(L,mid,l,r,ind<<1); S%=mod; if(r>mid) S+=query(mid+1,R,l,r,ind<<1|1); return S%mod; } void update(int L,int R,int l,int r,int ind) { if(cnt[ind]>=30) return ; if(L==R) { sum[ind]=quick_add(sum[ind],sum[ind]); cnt[ind]++; return ; } int mid=(L+R)>>1; if(l<=mid) update(L,mid,l,r,ind<<1); if(r>mid) update(mid+1,R,l,r,ind<<1|1); push_up(ind); } int main() { LL sm=5; for(int i=0;i<10;i++) for(int j=1;j<=i;j++) { sm=sm*sm%mod; printf("%llu\n",sm); } int n,t,m; scanf("%d",&t); for(int cas=1;cas<=t;cas++) { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%llu",&val[i]); Build(1,n,1); printf("Case #%d:\n",cas); LL Sum=0; while(m--) { int l,r; scanf("%d%d",&l,&r); Sum+=query(1,n,l,r,1); Sum%=mod; printf("%llu\n",Sum); update(1,n,l,r,1); } } return 0; }
相关文章推荐
- LaTex简历模板 Using the LaTeX Resume Templates
- leetcode:Minimum Depth of Binary Tree
- VS2015 C++/CLR
- XPath提取XML文档数据
- Activity的启动模式
- POJ 1274 - The Perfect Stall
- Algorithm-How To Identifying Same IMG
- java版strspn
- Box2D C++ 教程-查询 World
- 有哪些适合学生参与的 C++,网络编程方面的开源项目?
- 异常处理
- java向上转型和向下转型
- 关于js里undefined的重写问题
- 扩展欧几里德应用 hdoj 1222
- 【Microsoft Word】Aurora插入公式点击Refresh,提示Problems running LaTex解决方法
- 有哪些适合学生参与的 C++,网络编程方面的开源项目?
- 20分钟入门正则表达式
- 浏览器跨域问题
- <<的重载
- linux Cent-OS 安装中文输入法