8.22题解
果然,我只能改完B卷的题
T1
二分答案+贪心$check$,当然什么三分,数学题之类的都有写的,都可以
考场上实在太困了,左边界的$max$被我在神志不清的情况下写了个$min$,手扔20分,又一次离AC远去
1 #include<iostream> 2 #include<cstdio> 3 #define ll long long 4 using namespace std; 5 ll n,d,a,b,l,r; 6 inline bool check(ll midd) 7 { 8 ll cost; 9 if((midd-a)%d) cost=(midd-a)/d+1ll*1; 10 else cost=(midd-a)/d; 11 if((midd-b)%d) cost+=(midd-b)/d+1ll*1; 12 else cost+=(midd-b)/d; 13 if(cost<n) return 1; 14 else return 0; 15 } 16 int main() 17 { 18 scanf("%lld%lld%lld%lld",&n,&d,&a,&b); 19 l=max(a,b); r=a+n*d; 20 if(d==0) {printf("%lld",l); return 0;} 21 while(l<r) 22 { 23 if(l+1==r) 24 { 25 if(check(r)) l=r; 26 break; 27 } 28 ll mid=(l+r)>>1; 29 if(check(mid)) l=mid; 30 else r=mid-1; 31 } 32 printf("%lld\n",l); 33 return 0; 34 }
T2
考场上只想到了暴力,我也忘了有没有想到可以看某个值能作为几个区间的最大值这件事了,反正是没打就对了
这道题可以用两边单调栈,一边正着扫,找左边第一个大于它的位置,一边倒着扫,找右边第一个大于等于它的位置,最后他可做贡献的区间就是$(x-l){\times}(r-x)$,再维护一个前缀和,直接查询就可以了
1 #include<algorithm> 2 #include<iostream> 3 #include<cstring> 4 #include<cstdio> 5 #include<stack> 6 #define int long long 7 #define maxn 100100 8 #define inf 10000000 9 using namespace std; 10 int n,q; 11 char ss[3]; 12 int a[maxn],lsh[maxn],tong[maxn],qian[maxn]; 13 stack <int> s; 14 signed main() 15 { 16 scanf("%lld%lld",&n,&q); 17 for(int i=1;i<=n;++i) {scanf("%lld",&a[i]); lsh[i]=a[i];} 18 sort(lsh+1,lsh+n+1); 19 int len=unique(lsh+1,lsh+n+1)-lsh-1; 20 for(int i=1;i<=n;++i) a[i]=lower_bound(lsh+1,lsh+len+1,a[i])-lsh; 21 a[0]=inf; s.push(0); 22 for(int i=1;i<=n;++i)//单调减 23 { 24 while(a[s.top()]<=a[i]) s.pop(); 25 qian[i]=i-s.top(); 26 s.push(i); 27 } 28 while(s.size()) s.pop(); 29 a[n+1]=inf; s.push(n+1); 30 for(int i=n;i>=1;--i) 31 { 32 while(a[s.top()]<a[i]) s.pop(); 33 tong[a[i]]+=(s.top()-i)*qian[i]; 34 s.push(i); 35 } 36 for(int i=1;i<=n;++i) tong[i]+=tong[i-1]; 37 int tot=n*(n+1)/2; 38 for(int i=1;i<=q;++i) 39 { 40 int k; scanf("%s%lld",ss,&k); 41 if(ss[0]=='<') 42 { 43 k=lower_bound(lsh+1,lsh+len+1,k)-lsh; 44 printf("%lld\n",tong[k-1]); 45 } 46 else if(ss[0]=='=') 47 { 48 int ls=lower_bound(lsh+1,lsh+len+1,k)-lsh; 49 if(lsh[ls]!=k) printf("0\n"); 50 else printf("%lld\n",tong[ls]-tong[ls-1]); 51 } 52 else 53 { 54 int ls=lower_bound(lsh+1,lsh+len+1,k)-lsh; 55 if(lsh[ls]!=k) printf("%lld\n",tot-tong[ls-1]); 56 else printf("%lld\n",tot-tong[ls]); 57 } 58 } 59 return 0; 60 }
当然了,最好不要学我这么懒,$STL$库里的栈其实常熟还是挺大的,所以最好用数组模拟,自己手打栈,我太懒了而已
T3
考场一共两个人AC,全是打表找规律?一大佬还是用4个数,就是手模然后找出规律的$TQL$
关于学长的题解,你要是打表找规律确实没毛病,但是证明什么的我只能看懂等比数列求和,还颓了百度。。。。我对不起数学老师
1 #include<iostream> 2 #include<cstdio> 3 #define ll long long 4 #define maxn 100100 5 #define mod 1000000007 6 using namespace std; 7 int n; 8 ll ans; 9 ll mi[maxn]; 10 ll ksm(ll a,ll b) 11 { 12 ll ans=1; 13 while(b) 14 { 15 if(b&1) ans=(ans*a)%mod; 16 b=b>>1; a=(a*a)%mod; 17 } 18 return ans; 19 } 20 signed main() 21 { 22 scanf("%d",&n); mi[0]=1; 23 for(int i=1;i<=n;++i) mi[i]=(mi[i-1]*2)%mod; 24 for(int i=2;i<=n;++i) ans=(ans+(mi[i-1]-1)*ksm(1ll*i,mod-2)%mod)%mod; 25 printf("%lld\n",ans); 26 return 0; 27 }