牛客寒假训练营3 F牛牛的Link Power I

题目描述

链接:https://ac.nowcoder.com/acm/contest/3004/F
来源:牛客网

题目描述

牛牛有一颗大小为n的神奇Link-Cut 数组,数组上的每一个节点都有两种状态,一种为link状态,另一种为cut状态。数组上任意一对处于link状态的无序点对(即(u,v)和(v,u)被认为是同一对)会产生dis(u,v)的link能量,dis(u,v)为数组上u到v的距离。

我们定义整个数组的Link能量为所有处于link状态的节点产生的link能量之和。

一开始数组上每个节点的状态将由一个长度大小为n的01串给出,'1’表示Link状态,'0’表示Cut状态。

牛牛想要知道整个数组的Link能量,为了避免这个数字过于庞大,你只用输出答案对109+710^9+7109+7取余后的结果即可。
输入描述:

第一行输入一个正整数n(1≤n≤105)(1 \leq n \leq 10^5)(1≤n≤105)

接下里一行输入一个长度大小为n的01串表示数组的初始状态,'1’表示Link状态,'0’表示Cut状态。

输出描述:

仅一行,表示整个数组的Link能量对109+710^9+7109+7取余后的结果。

示例1
输入

3
101

输出

2

示例2
输入

5
00110

输出

1

示例3
输入

6
000010

输出

0

解法一 前缀和

前缀和的思路,但是要用到两次前缀和。首先,先把字符型数组ch中的字符传入长整型数组em中,然后,对em进行2次前缀和处理。
不知道为啥要进行2次前缀和处理的,可以解除“/* */”封印,看一下数据:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll mod=1e9+7;
int n;
char ch[100010];
ll em[100010];
int main(){
         ll um=0;
         scanf("%d",&n);
         scanf("%s",ch);
         for(int i=0;ch[i];i++){
               if(ch[i]=='1'){
                              em[i+1]++;//转换字符
               }
         }
         /*for(int i=1;i<=n;i++){
               printf("%lld ",em[i]);
         }
         printf("\n");*/
         for(int i=1;i<=n;i++){
               em[i]+=em[i-1];      //前缀和
               em[i]%=mod;
         }
         /*for(int i=1;i<=n;i++){
               printf("%lld ",em[i]);
         }
         printf("\n");*/
         for(int i=1;i<=n;i++){
               em[i]+=em[i-1];      //前缀和
               em[i]%=mod;
         }
         /*for(int i=1;i<=n;i++){
               printf("%lld ",em[i]);
         }
         printf("\n");*/
         for(int i=1;i<=n;i++){  //ch[0]不用计入
               if(ch[i]=='1'){
                              um+=em[i];
                              um%=mod;
               }
         }
         printf("%lld\n",um);
         return 0;
}

解法二

解法二更容易想到,并且空间复杂度比较低,时间:O(n),空间:O(1)。
先把ch中为‘1’的位置记录至em中,例如:em[5]={1,3,5,6,7}:
在这里插入图片描述所以,就变成了只要知道前后两个的位置差距就行了!

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll mod=1e9+7;
ll n;
char ch[100010];
ll em[100010];
int main(){
         scanf("%lld",&n);
         ll jj=0;
         scanf("%s",ch);
         for(int i=0;i<n;i++){
               if(ch[i]=='1'){
                              em[jj++]=i;
               }
         }
         ll sum=0;
         for(int i=1;i<jj;i++){
               sum=sum%mod+((em[i]-em[i-1])*i*(jj-i))%mod;
         }
         printf("%lld\n",sum);
         return 0;
}
发布了36 篇原创文章 · 获赞 1 · 访问量 1386

猜你喜欢

转载自blog.csdn.net/atnanajiang/article/details/104239808