Codeforces Round #553 (Div. 2) C. Problem for Nazar ###K //K
题目链接:https://codeforces.ml/contest/1151/problem/C
题意:有两个无限的奇数集合和偶数集合 构造一个新的数组,先是放前2^0 个奇数, 然后集合中移除这些数,在放2^1 个偶数 进去新的数组,重复操作
思路:看见2的幂 就知道可以直接来logn模拟了, 自己做的时候考虑的时候是用前缀和记录每一份奇数和偶数有多少个,并且记录下每一份的长度和首项,后面用等差数列来求和即可
中间的直接相加,唯有前面多出来的一点和后面多出来的一点要处理一下, 不过要注意可能没有中间部分,即只有一段要单独处理一下
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 #define pb push_back 5 const int maxn =2e5+10; 6 const int mod=1e9+7; 7 ll a[100]; 8 ll len[100]; 9 ll pre[maxn]; 10 11 12 13 int main() 14 { 15 ios::sync_with_stdio(false); 16 cin.tie(0); 17 ll l,r; 18 cin>>l>>r; 19 ll g=1; 20 ll cnt1=1; 21 ll cnt2=2; 22 for(int i=1;i<=60;i++) 23 { 24 len[i]=g; 25 g*=2; 26 if(i%2) 27 { 28 a[i]=cnt1; 29 cnt1+=1ll*len[i]*2; 30 } 31 else 32 { 33 a[i]=cnt2; 34 cnt2+=1ll*len[i]*2; 35 } 36 } 37 38 ll ans=0; 39 for(int i=1;i<=60;i++) 40 { 41 pre[i]=pre[i-1]+len[i]; 42 } 43 int p=lower_bound(pre+1,pre+1+60,l)-pre; 44 int pos=lower_bound(pre+1,pre+1+60,r)-pre; 45 if(p==pos) 46 { 47 ll len2=r-pre[p-1]; 48 ll temp=a[p]%mod*(len2%mod)+len2%mod*((len2%mod-1+mod)%mod); 49 temp%=mod; 50 ans+=temp; 51 ans%=mod; 52 ll len3=l%mod-pre[p-1]%mod-1; 53 len3=(len3+mod)%mod; 54 ll temp2=a[p]%mod*(len3%mod)+len3%mod*((len3%mod-1+mod)%mod); 55 temp2%=mod; 56 ans-=temp2; 57 ans=(ans+mod)%mod; 58 cout<<ans<<'\n'; 59 return 0; 60 } 61 62 for(int i=p+1;i<=pos-1;i++) 63 { 64 ll temp=a[i]%mod*(len[i]%mod)+len[i]%mod*((len[i]%mod-1+mod)%mod); 65 temp%=mod; 66 ans+=temp; 67 ans%=mod; 68 } 69 70 ll len2=r-pre[pos-1]; 71 ll temp2=(len2%mod*(a[pos]%mod)); 72 temp2%=mod; 73 ll temp3=((len2%mod-1+mod)%mod)*(len2%mod); 74 temp3%=mod; 75 ans+=temp2+temp3; 76 ans%=mod; 77 78 79 ll len1=pre[p]%mod-l%mod+1; 80 len1=(len1+mod)%mod; 81 ll a1=a[p]%mod+(len[p]%mod-len1%mod+mod)%mod*2; 82 ll temp1=(len1%mod*(a1%mod))%mod; 83 ll temp4=((len1%mod-1+mod)%mod)*(len1%mod); 84 temp4%=mod; 85 temp1%=mod; 86 ans+=temp1+temp4; 87 ans%=mod; 88 cout<<ans<<'\n'; 89 90 91 92 }
这种1~n的排列 尽量往等差数列求和的方向去想
题解的做法是直接求出所要求的范围内的奇数和偶数的个数 然后由等差数列 前n个奇数的和为n^2 前n个偶数的和为n*(n+1)
答案即为F(r)-F(l-1) 取模要注意每个地方都要取到, 不然很容易出负数
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 #define pb push_back 5 const int maxn =2e5+10; 6 const int mod=1e9+7; 7 8 ll cal(ll x) 9 { 10 ll odd=0,even=0,f=1,sum=1; 11 while(x-sum>=0) 12 { 13 x-=sum; 14 if(f%2) 15 { 16 odd+=sum; 17 } 18 else 19 even+=sum; 20 sum*=2; 21 f++; 22 } 23 if(f%2) 24 odd+=x; 25 else 26 even+=x; 27 return ((odd%mod*(odd%mod))%mod+(even%mod*((even+1)%mod))%mod)%mod; 28 } 29 30 31 int main() 32 { 33 ios::sync_with_stdio(false); 34 cin.tie(0); 35 ll l,r; 36 cin>>l>>r; 37 ll ans=cal(r)-cal(l-1); 38 ans=(ans+mod)%mod; 39 cout<<ans<<'\n'; 40 41 42 }

浙公网安备 33010602011771号