ICM Technex 2017 and Codeforces Round #400 (Div. 1 + Div. 2, combined) C. Molly’s Chemicals

cf开virtual写到这道题的时候感觉题面很简单,感觉上和自己昨天写的一道莫队的题目很相似,那道题目是让你找有多少个区间的区间和是0,这道题是找有多少个区间的区间和是k的整数次幂。
这道题的n
的范围是1e5,那莫队n
sqrt(n)
肯定是解决不了的. 仔细想了一下这样找区间多半是O(n)
的查询,因为个人感觉在这里二分区间也没啥用。O(n)
的查询的话,我们记录一下每一位的前缀和,做差便得到了两个下标间的区间和。
在这里发散一下思维,如果我们用max
哈希的记录前缀和数值是否存在,这样对每一位k的幂级数而言,我们只要O(n)
的就能找出是否存在该区间和。
k
的范围是[-10~10]真的是深坑啊,在预处理k的幂级数的时候忘了考虑-1和1的情况了,导致一直while死循环re了5发⊙︿⊙ 这样最多62n的时间复杂度下便可得到正解。
唉,这题wa了11发才过,最近的bug率很高啊,该调整心态了。
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<cmath> #include<vector> #include<set> #include<queue> #include<limits.h> #include<string.h> #include<map> using namespace std; typedef long long ll; #define inf int(0x3f3f3f3f) #define mod int(1e9+7) #define eps double(1e-6) #define pi acos(-1.0) #define lson root << 1 #define rson root << 1 | 1 ll n,k; ll a[100005]; map<ll,ll> mp; vector<ll> mi; ll powmod(ll a,ll b) { ll ans = 1; while(b) { if(b&1) { ans = (ans*a); b--; } b/=2; a = a*a; } return ans; } void init(ll k) { int cnt=0; while(1) { //cout<<111<<endl; if(k==-1) mi.push_back(-1); if(k==-1||k==1) { mi.push_back(1); break; } else { mi.push_back(powmod(k,cnt)); cnt++; //cout<<pos<<endl; ll shu=powmod(k,cnt-1); if(shu>=1e15) break; } } } int main() { //cout<<powmod(-1,2)<<endl; ios::sync_with_stdio(false); cin.tie(0); cin>>n>>k; memset(a,0,sizeof(a)); for(ll i=1; i<=n; i++) { cin>>a[i]; a[i]+=a[i-1]; } init(k); ll sum=0; //cout<<mi[0]<<endl; //cout<<pos<<endl; for(ll i=0; i<mi.size(); i++) { //cout<<mi[i]<<endl; //cout<<111<<endl; mp.clear(); ll pownum=mi[i]; for(ll j=1; j<=n; j++) { //cout<<a[j-1]<<endl; mp[a[j-1]]++; if(mp.count(a[j]-pownum)) { sum+=mp[a[j]-pownum]; //cout<<mp[a[j]-pownum]<<endl; } } } cout<<sum<<endl; }
发表评论