搜索(四分树):BZOJ 4513 [SDOI2016 Round1] 储能表

4513: [Sdoi2016]储能表

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 395  Solved: 213
[Submit][Status][Discuss]

Description

有一个 n 行 m 列的表格,行从 0 到 n−1 编号,列从 0 到 m−1 编号。每个格子都储存着能量。最初,第 i 行第 j 列的格子储存着 (i xor j) 点能量。所以,整个表格储存的总能量是,

随着时间的推移,格子中的能量会渐渐减少。一个时间单位,每个格子中的能量都会减少 1。显然,一个格子的能量减少到 0 之后就不会再减少了。
也就是说,k 个时间单位后,整个表格储存的总能量是,
给出一个表格,求 k 个时间单位后它储存的总能量。
由于总能量可能较大,输出时对 p 取模。

Input

第一行一个整数 T,表示数据组数。接下来 T 行,每行四个整数 n、m、k、p。

Output

 共 T 行,每行一个数,表示总能量对 p 取模后的结果

Sample Input

3
2 2 0 100
3 3 0 100
3 3 1 100

Sample Output

2
12
6

HINT

 T=5000,n≤10^18,m≤10^18,k≤10^18,p≤10^9

 

  找规律的方法过的。

  思路在程序中很清楚,用四分树搜索。

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 using namespace std;
 5 typedef long long LL;
 6 
 7 LL n,m,k,mod,len;
 8 LL Max(LL a,LL b){
 9     return a>b?a:b;
10 }
11 
12 LL Mul(LL a,LL b){
13     LL ret=0;
14     a%=mod;b%=mod;
15     while(a){
16         if(a&1)ret=(ret+b)%mod;
17         a>>=1;b<<=1;
18     }
19     return ret;
20 }
21 
22 LL Calc1(LL h,LL tot){
23     LL t=h+tot-1,ret=0;
24     h=Max(1,h-k);t-=k;
25     if(h>t)return 0;
26     if((h+t)&1) ret=Mul(Mul((h+t),(t-h+1)/2),tot);
27     else ret=Mul(Mul((t-h+1),((h+t)/2)),tot);
28     return ret;
29 }
30 
31 LL Calc2(LL h,LL t,LL lb){
32     LL ret=0;
33     h=Max(1ll,h-k);t-=k;
34     if(h>t)return 0;
35     if((h+t)&1) ret=Mul(Mul((h+t),(t-h+1)/2),lb);
36     else ret=Mul(Mul((t-h+1),((h+t)/2)),lb);
37     return ret;
38 }
39 
40 LL Solve(LL qa,LL qb,LL x1,LL y1,LL x2,LL y2,LL l){
41     if(x1<y1){swap(qa,qb);swap(x1,y1);swap(x2,y2);}    
42     if(qa>=x2&&qb>=y2){return Calc1(x1^y1,l);}
43     else if(qa>=x2){return Calc2(x1^y1,(x1^y1)+l-1,qb-y1);}
44     else if(qb>=y2){return Calc2(x1^y1,(x1^y1)+l-1,qa-x1);}
45     LL mx=(x1+x2)>>1,my=(y1+y2)>>1,ret=0;
46     if(x1<qa&&y1<qb)ret=(ret+Solve(qa,qb,x1,y1,mx,my,l>>1))%mod;
47     if(mx<qa&&y1<qb)ret=(ret+Solve(qa,qb,mx,y1,x2,my,l>>1))%mod;
48     if(x1<qa&&my<qb)ret=(ret+Solve(qa,qb,x1,my,mx,y2,l>>1))%mod;
49     if(mx<qa&&my<qb)ret=(ret+Solve(qa,qb,mx,my,x2,y2,l>>1))%mod;    
50     return ret;
51 }
52 int main(){
53     int T;
54     scanf("%d",&T);
55     while(T--){
56         scanf("%lld%lld%lld%lld",&n,&m,&k,&mod);
57         if(n<m)swap(n,m);len=1;
58         while(len<n)len<<=1;
59         printf("%lld\n",Solve(n,m,0,0,len,len,len));
60     }
61     return 0;    
62 }

 

posted @ 2016-06-11 16:07  TenderRun  阅读(499)  评论(0编辑  收藏  举报