In this problem, subarray is defined as non-empty sequence of consecutive elements.
We define a subarray as Super Subarray if the summation of all elements in the subarray is divisible by each element in it.
Given an array a of size n, print the number of Super Subarrays in a.
Input
The first line of the input contains a single integer T (1 ≤ T ≤ 100), the number of test cases.
The first line of each test case contains one integer n (1 ≤ n ≤ 2000), the length of array a.
The second line of each test case contains the sequence of elements of the array a1, a2, ..., an (1 ≤ ai ≤ 109), ai is the i-th element of the array a.
Output
For each test case, print a single integer that represents the number of Super Subarrays in a, on a single line.
Example
Input
2
5
1 2 3 4 5
5
2 3 4 3 6
Output
6
6
题意:给一个n个大小的数组,求给数组中有几个超子数组,超子数组的意思是:子区间的区间和是该区间各个元素的倍数。
解题思路:用前缀和保存子区间的和,再求出该区间lcm最小公倍数。再比较区间和是不是lcm最小公倍数的倍数,是则符合条件
一个坑点就是要剪枝,要判断一下lcm最小公倍数是否大于最大区间和,大于直接break。因为后面已经无法达到要求了。
代码:
//求数组中有几个区间的 区间和是该区间每个元素的倍数 #include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #define ll long long using namespace std; ll a[2050],sum[2050]; ll gcd(ll a,ll b)//最大公约数 { return b==0?a:gcd(b,a%b); } ll lcm(ll a,ll b)//最小公倍数 { return a/gcd(a,b)*b; } int main() { int t; cin>>t; while(t--) { int n,ans=0; cin>>n; for(int i=0;i<n;i++) cin>>a[i]; sum[0]=a[0]; for(int i=1;i<n;i++) sum[i]=sum[i-1]+a[i];//前缀和 for(int i=0;i<n;i++) { ll temp=a[i]; for(int j=i;j<n;j++) { temp=lcm(temp,a[j]);//i到当前j区间的最小公倍数 ll num=sum[j]-sum[i-1];//i到当前j区间的区间和 if(temp>sum[n-1])//剪枝,最小公倍数大于sum[n-1](最大的区间和) break; else if(num%temp==0)//符合条件计数器加1 ans++; } } cout<<ans<<endl; } return 0; }