Codeforces Round #553 (Div. 2) C 等差數列求和 + 前綴和
阿新 • • 發佈:2019-05-05
求和 inline fin ons urn long long esp 計算 long
https://codeforces.com/contest/1151/problem/C
題意
有兩個等差數列(1,3,5,..),(2,4,6,...),兩個數列輪流取1,2,4,...,\(2^n\)組成一個新的數列,然後詢問區間l,r的和
題解
- 一開始總想著怎麽計算中間那一段,其實用前綴和很好處理
- 數太大,第二個數也要取模才能相乘
代碼
#include<bits/stdc++.h> #define ll long long using namespace std; const ll cha=2; const ll P = 1e9+7; ll pw(ll bs,ll x){ ll ans=1; while(x){ if(x&1)ans*=bs; bs*=bs; x>>=1; } return ans; } ll pw(ll bs,ll x,ll MOD){ ll ans=1; while(x){ if(x&1)ans=ans*bs%MOD; bs=bs*bs%MOD; x>>=1; } return ans; } const ll pw2=pw(2,P-2,P); ll cal(ll x){ ll i=1;int odd=1; ll od=1,ed=2,d,lt; ll ans=0; while(x>=pw(2,i-1)){ //cout<<i<<" "<<ans<<endl; //cout<<od<<" "<<ed<<endl; x-=pw(2,i-1); d=pw(2,i-1); if(odd){ ans+=(od%P*(d%P)%P+d%P*((d-1)%P)%P)%P; ans%=P; od+=d*cha; }else{ ans+=(ed%P*(d%P)%P+d%P*((d-1)%P)%P)%P; ans%=P; ed+=d*cha; } odd^=1; i++; } //cout<<i<<endl; //cout<<ans<<endl; if(x==0)return ans; d=x; if(odd){ ans+=(od%P*(d%P)%P+d%P*((d-1)%P)%P)%P; ans%=P; od+=d*cha; }else{ ans+=(ed%P*(d%P)%P+d%P*((d-1)%P)%P)%P; ans%=P; ed+=d*cha; } return ans; } int main(){ ll l,r; cin>>l>>r; cout<<(cal(r)-cal(l-1)+P)%P; }
Codeforces Round #553 (Div. 2) C 等差數列求和 + 前綴和