四川大学新生赛——羊工八刀

四川大学的新生赛的一道题目
感谢大佬教我的
思路:让求两个1的距离的平方之和
有点像 ( a − b ) 2 = a 2 + b 2 − 2 a b (a - b) ^2 = a ^ 2 + b ^ 2 - 2ab (ab)2=a2+b22ab这个公式,这样我们就可以推出柿子,两个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 (a2a1)2=a12+a222a1a2
当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 (a2a1)2=a12+a222a1a2
( 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 (a3a1)2=a12+a322a1a3
( 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 (a3a2)2=a22+a322a2a3
公式就是所有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 ;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值