四川大学的新生赛的一道题目
感谢大佬教我的
思路:让求两个1的距离的平方之和
有点像
(
a
−
b
)
2
=
a
2
+
b
2
−
2
a
b
(a - b) ^2 = a ^ 2 + b ^ 2 - 2ab
(a−b)2=a2+b2−2ab这个公式,这样我们就可以推出柿子,两个1的距离的平方之和就是所有
当1的个数为2个时
(
a
2
−
a
1
)
2
=
a
1
2
+
a
2
2
−
2
a
1
a
2
(a_2-a_1) ^ 2 = a_1 ^2 + a_2 ^2 - 2a _1a_2
(a2−a1)2=a12+a22−2a1a2
当1的个数为3个时
(
a
2
−
a
1
)
2
=
a
1
2
+
a
2
2
−
2
a
1
a
2
(a_2 - a_1)^2 = a_1^2 + a_2^2 - 2a_1a_2
(a2−a1)2=a12+a22−2a1a2
(
a
3
−
a
1
)
2
=
a
1
2
+
a
3
2
−
2
a
1
a
3
(a_3 - a_1) ^2 = a_1 ^2 + a_3 ^2 - 2a_1a_3
(a3−a1)2=a12+a32−2a1a3
(
a
3
−
a
2
)
2
=
a
2
2
+
a
3
2
−
2
a
2
a
3
(a_3 - a_2) ^2 = a_2 ^2 + a_3 ^2 - 2a_2a_3
(a3−a2)2=a22+a32−2a2a3
公式就是所有1的位置乘以(1的个数-1)减去1后面1的前缀和
#include <bits/stdc++.h>
using namespace std ;
long long n ;
const int N = 1000010 ;
const int mod = 1e9 + 7 ;
long long f[N] ;
char s[N] ;
//(a-b)^2 = a^2 +b^2 - 2ab //n * n的话 2ab出现两次
//(a-a)^2 = 0
int main()
{
int t ;
cin >> t ;
while (t -- ){
cin >> n ;
cin >> s + 1 ;
vector<int>a ;
int cnt = 1 ;
for (int i = 1; i <= n; i ++ ) {
if (s[i] == '1') {
a.push_back(i) ;
f[cnt] = (f[cnt - 1] + i) % mod ;
cnt ++ ;
}
}
if (cnt - 1 <= 1) {
cout << 0 << endl ;
continue ;
}
long long sum = 0 ;
for (int i = a.size() - 1; i >= 0; i -- ){
sum = (sum + ((long long)(a.size() - 1) * a[i] % mod) * a[i] % mod ) % mod ;
sum = (sum - 2 * a[i] * f[i] % mod + mod) % mod ;//a[i]和他后面所以的1结合
}
cout << sum % mod << endl ;
}
return 0 ;
}