1. 程式人生 > >【Codeforces Round #520 C.Banh-mi】字首和+

【Codeforces Round #520 C.Banh-mi】字首和+

C. Banh-mi

題意

01q題意就是給你一個01串,q次詢問每次詢問一段區間 0011每次詢問詢問的是:最初區間內0的權值是0,1的權值是1 每次可以移出一個字元,移除後答案加上該字元的權值 其餘所有字元加上該字元的權值

最後詢問每個區間內能獲得的最大答案,每次查詢是獨立的

做法

110首先我們發現,對每個區間來說,一定是一直拿1,1沒有了拿0這個策略 10所以問題就變為給你一個先1後0的序列來計算上面的問題 01而這個序列中0,1的個數我們都可以通過字首和快速計算出來

11我們發現對於每個1的區間,對答案的貢獻是一段首項為1 21公比為2,長度為1的個數等比數列 01對於每個0的區間,對答案的貢獻是一段首項為1那段區間對答案的貢獻 20公比為2,長度為0的個數的等比數列
之後加個快速冪再加個字首和預處理這道題就做完了“”

坑點

Mod有減法要加Mod%Mod

程式碼

#include<iostream>
#include<math.h>
#include<stdio.h>
#include<algorithm>
#include<queue>
#include<map>
#include<bitset>
#include<stack>
#include<set>
#include<vector>
#include <time.h>
#include<string.h>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef double db;
typedef pair <int, int> pii;
typedef pair <ll, ll> pll;
typedef pair <ll, int> pli;
typedef pair <db, db> pdd;

const int maxn = 1e5+5;
const int Mod=1000000007;
const int INF = 0x3f3f3f3f;
const ll LL_INF = 0x3f3f3f3f3f3f3f3f;
const double e=exp(1);
const db PI = acos(-1);
const db ERR = 1e-10;

#define Se second
#define Fi first
#define pb push_back
#define dbg(x) cout<<#x<<" = "<< (x)<< endl
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl
ll pow_(ll a,ll b)
{
    ll ans=1;
    while(b)
    {
        if(b&1) ans=(ans*a)%Mod;
        b>>=1;
        a=(a*a)%Mod;
    }
    return ans;
}
ll inv(ll x)
{
    return pow_(x,Mod-2);
}
ll sum[maxn][2];
char str[maxn];
int main()
{
    //ios::sync_with_stdio(false);
    //freopen("a.txt","r",stdin);
    //freopen("b.txt","w",stdout);
    int n,q;
    scanf("%d%d",&n,&q);
    scanf("%s",str+1);
    for(int i=1;i<=n;i++)
    {
        sum[i][0]=sum[i-1][0];
        sum[i][1]=sum[i-1][1];
        if(str[i]=='0') sum[i][0]=(sum[i][0]+1)%Mod;
        else sum[i][1]=(sum[i][1]+1)%Mod;;
    }
    while(q--)
    {
        int l,r;
        scanf("%d%d",&l,&r);
        ll sum0=(sum[r][0]-sum[l-1][0]+Mod)%Mod;
        ll sum1=(sum[r][1]-sum[l-1][1]+Mod)%Mod;
        ll ans=0;
        ans=(pow_(2,sum1)-1+Mod)%Mod;
        ll st=(pow_(2,sum1)-1+Mod)%Mod;
        ll tmp=(pow_(2,sum0)-1+Mod)%Mod;
        tmp=(tmp*st)%Mod;
        ans=(ans+tmp)%Mod;
        printf("%lld\n",ans);
    }
    //cout << "time: " << (long long)clock() * 1000 / CLOCKS_PER_SEC << " ms" << endl;
    return 0;
}