http://acm.hdu.edu.cn/showproblem.php?pid=3030
本来想的是DP的算法,但是DP的话明显要超时的。
然后文哥告诉我的用树状数组的方法,我一直想怎么用树状数组来表示。。
看文哥模拟,然后知道。。。
想将数组离散化,然后记录第i个位置为结尾的序列的个数(就是DP的思想了)。。
并且每次都要更新以 第 i 个元素为结尾的序列的当前的个数,这里用到了树状数组更新。
View Code
1 #include <iostream> 2 #include <algorithm> 3 using namespace std; 4 const int maxn = 500005; 5 const int mod = 1000000007; 6 long long ans[maxn],has[maxn],temp[maxn],x,y,z,n,m; 7 8 int lowbit(int i) 9 { 10 return i & (-i); 11 } 12 13 long long getSum(int i) 14 { 15 long long sum=0; 16 while(i) 17 { 18 sum+=temp[i]; 19 sum%=mod; 20 i-=lowbit(i); 21 } 22 return sum; 23 } 24 25 void modfiy(int i,int c) 26 { 27 while(i<maxn) 28 { 29 temp[i]+=c; 30 i+=lowbit(i); 31 } 32 } 33 34 void make() 35 { 36 int i,j; 37 j=1; 38 if(m>=n) 39 { 40 for(i=0;i<n;i++) 41 ans[j++]=has[i]; 42 43 } 44 else 45 { 46 for(i=0;i<n;i++) 47 { 48 ans[j++]=has[i%m]; 49 has[i%m]=(x*has[i%m]+y*(i+1))%z; 50 } 51 } 52 for(i=1;i<=n;i++) 53 temp[i]=ans[i]; 54 sort(temp+1,temp+n+1); 55 has[1]=temp[1]; 56 for(i=2,j=2;i<=n;i++) 57 if(temp[i]!=temp[i-1]) 58 has[j++]=temp[i]; 59 m=j; 60 } 61 62 int search(long long num) 63 { 64 int i,j,mid; 65 i=1; j=m-1; 66 while(i<=j) 67 { 68 mid=(i+j)/2; 69 if(num==has[mid]) 70 return mid; 71 if(num>has[mid]) 72 i=mid+1; 73 else 74 j=mid-1; 75 76 } 77 return mid; 78 } 79 80 81 int main() 82 { 83 int t,i,j,l,ch; 84 cin>>t; 85 for(l=1;l<=t;l++) 86 { 87 cin>>n>>m>>x>>y>>z; 88 for(i=0;i<m;i++) 89 cin>>has[i]; 90 make(); 91 for(i=0;i<maxn;i++) 92 temp[i]=0; 93 for(i=1;i<=n;i++) 94 { 95 ch=search(ans[i]); 96 ans[i]=getSum(ch-1)+1; 97 modfiy(ch,ans[i]); 98 } 99 long long sum=0; 100 cout<<"Case #"<<l<<": "; 101 for(i=1;i<=n;i++) 102 sum=(sum+ans[i])%mod; 103 cout<<sum<<endl; 104 } 105 return 0; 106 }