题目给的这个模数很神奇 其实是2^63-2^31这个值 找规律发现 在摸这个数的前提下 对任何一个数平方运算不超过30次就变为一个恒定值 就可以用剪枝搞一搞 类似于开根号的题型 难在找规律
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define ll unsigned long long #define M 9223372034707292160 struct node { int l; int r; ll val; int cnt; int flag; }; node tree[400010]; ll num[100010]; int n,q; ll getmul(ll a,ll b) { ll res; res=0; while(b>0) { if(b%2) res=(res+a)%M; a=(a+a)%M,b/=2; } return res; } void pushup(int cur) { tree[cur].val=(tree[2*cur].val+tree[2*cur+1].val)%M; tree[cur].flag=tree[2*cur].flag&tree[2*cur+1].flag; return; } void build(int l,int r,int cur) { int m; tree[cur].l=l; tree[cur].r=r; tree[cur].val=0; tree[cur].cnt=0; tree[cur].flag=0; if(l==r) { scanf("%lld",&tree[cur].val); return; } m=(l+r)/2; build(l,m,2*cur); build(m+1,r,2*cur+1); pushup(cur); return; } ll query(int pl,int pr,int cur) { ll res; if(pl<=tree[cur].l&&tree[cur].r<=pr) { return tree[cur].val; } res=0; if(pl<=tree[2*cur].r) res=(res+query(pl,pr,2*cur))%M; if(pr>=tree[2*cur+1].l) res=(res+query(pl,pr,2*cur+1))%M; return res; } void update(int pl,int pr,int cur) { if(tree[cur].flag) return; if(tree[cur].l==tree[cur].r) { tree[cur].val=getmul(tree[cur].val,tree[cur].val); tree[cur].cnt++; if(tree[cur].cnt==29) tree[cur].flag=1; return; } if(pl<=tree[2*cur].r) update(pl,pr,2*cur); if(pr>=tree[2*cur+1].l) update(pl,pr,2*cur+1); pushup(cur); return; } int main() { ll ans; int t,cas,i,l,r; scanf("%d",&t); for(cas=1;cas<=t;cas++) { scanf("%d%d",&n,&q); build(1,n,1); ans=0; printf("Case #%d:\n",cas); while(q--) { scanf("%d%d",&l,&r); ans=(ans+query(l,r,1))%M; update(l,r,1); printf("%lld\n",ans%M); } } return 0; } /* 5 3 10 9223372034707292159 9223372034707292159 9223372034707292159 1 2 1 2 1 2 1 2 1 2 */