【CF314C】Sereja and Subsequences(DP,树状数组)
题意:给定一个N个数的数列,求所有不同不下降子序列的乘积之和,其中不同指的是组成它的数字和长度不完全相同
n (1 ≤ n ≤ 10^5) a[i]<=10^6
思路:考虑DP。设DP[a[i]]为最后一位为a[i]时所有序列的积之和,则dp[a[i]]=a[i]+sigma(dp[a[j]]) *a[i] (a[j]<=a[i],j<i)
后一部分可以用树状数组计算
为了去除最后一位相同的序列比如1 2 2 这个序列中1 2这个子序列只能算一遍
要强行去掉原来最后一位为a[i]的序列
1 const mo=1000000007; 2 var dp:array[1..1100000]of int64; 3 n,i:longint; 4 s1,s2,t,ans,x:int64; 5 6 function lowbit(x:longint):longint; 7 begin 8 exit(x and (-x)); 9 end; 10 11 function sum(x:longint):int64; 12 var t:int64; 13 begin 14 t:=0; 15 while x>0 do 16 begin 17 t:=(t+dp[x]) mod mo; 18 x:=x-lowbit(x); 19 end; 20 exit(t); 21 end; 22 23 procedure add(x,s:longint); 24 begin 25 while x<=1000000 do 26 begin 27 dp[x]:=(dp[x]+s) mod mo; 28 x:=x+lowbit(x); 29 end; 30 end; 31 32 33 begin 34 //assign(input,'314C.in'); reset(input); 35 //assign(output,'314C.out'); rewrite(output); 36 readln(n); 37 for i:=1 to n do 38 begin 39 read(x); 40 s1:=sum(x); s2:=sum(x-1); 41 t:=(s1+1) mod mo*(x mod mo) mod mo; 42 t:=(t-(s1-s2) mod mo) mod mo; 43 t:=(t+mo) mod mo; 44 add(x,t); 45 ans:=(ans+t) mod mo; 46 end; 47 writeln(ans); 48 //close(input); 49 //close(output); 50 end.
null