传送门:http://codeforces.com/problemset/problem/1062/C
思路:先求出每个位置1和0个数的前缀和,肯定先干掉所有的1,再搞0,。所以可以这样推↓
于是就可以O1查询了!
代码:
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<string>
#include<iostream>
#include<map>
#include<vector>
#include<set>
#include<queue>
using namespace std;
typedef long long ll;
const ll maxv=1e5+5;
const ll mod=1e9+7;
ll quick_pow(ll a,ll b,ll m)
{
ll ans=1;
while(b>0)
{
if(b&1)
{
ans=ans*a%m;
}
a=a*a%m;
b>>=1;
}
return ans;
}
string s;
ll zero[maxv],one[maxv];
int main()
{
ll n,q;
cin>>n>>q;
zero[0]=one[0]=0;
cin>>s;
for(ll i=0;i<n;i++)
{
if(s[i]=='1')
{
zero[i+1]=zero[i];
one[i+1]=one[i]+1;
}
else
{
zero[i+1]=zero[i]+1;
one[i+1]=one[i];
}
}
while(q--)
{
ll st,ed;
cin>>st>>ed;
ll x=one[ed]-one[st-1];
ll y=zero[ed]-zero[st-1];
ll ans=((quick_pow(2,x,mod)-1)*quick_pow(2,y,mod))%mod;
cout<<ans<<endl;
}
return 0;
}