E -- array
Time Limit:3s Memory Limit:64MByte
Submissions:444Solved:130
DESCRIPTION
2 array is an array, which looks like:
1,2,4,8,16,32,64......1,2,4,8,16,32,64......
a1=1 | ai+1ai=2a1=1 | ai+1ai=2
Give you a number array, and your mission is to get the number of subsequences ,which is 2 array, of it.
Note: 2 array is a finite array.
INPUT
There are multiple test cases.The first line is a number T (
T ≤10T ≤10), which means the number of cases.For each case, two integer
n(1≤n≤105)n(1≤n≤105).The next line contains
nn numbers
ai(1≤ai≤109)ai(1≤ai≤109)
OUTPUT
one line - the number of subsequence which is 2 array.(the answer will
% 109+7% 109+7)
SAMPLE INPUT
241 2 1 241 2 4 4
SAMPLE OUTPUT
54
SOLUTION
题意:给你n个数,让你求从1开始的,后面每一项大于前一位的“2 array”
思路:
官方题解:
#E. dp
注意到109109范围内的22的幂次只有3030个,所以我们定义dp[30]dp[30]这样一个dp数组,dp[i]dp[i]表示以2i2i为结尾的满足条件的子序列的个数。枚举每一个数来转移,复杂度O(32n)-O(n)?
我的dp好菜啊,没写出来
下面是Rapiz给的代码,感谢,贴上学习下,(中学生好强!
//Rapiz
#include<cstdio>
#include<cstring>
const int N=1e5+10,M=1e9+7;
int ispow(int x){
int r=0;
while(x%2==0) x/=2,++r;
return x==1?r:-1;
}
int a[N],f[N][32];
int main(){
int T;scanf("%d",&T);
while(T--){
int n;scanf("%d",&n);
memset(f,0,sizeof(f));
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
f[i][0]=f[i-1][0]+(a[i]==1);
f[i][0]%=M;
}
for(int i=1;i<=n;i++) for(int j=1;j<32;j++) {
f[i][j]=f[i-1][j]%M;
int r=ispow(a[i]);
if(r==j) f[i][j]+=f[i-1][j-1],f[i][j]%=M;
}
int ans=0;
for(int i=0;i<32;i++) ans=(ans+f[n][i])%M;
printf("%d\n",ans);
}
}