9.14题解

T1

对于这个数据范围,我们发现我们不断的乘$b$,什么都不加,$b$是最小的2,$T$是最小的1,最多也就乘大概60次就足够了,也就是说我们完全可以枚举乘过几个$b$,既然我们确定了需要乘几个$b$,那加$a$也就可以确定了,我们可以得到$m{ imes}a=T-S{ imes}b^x$,我们就可以得到m的值,而关键就是求出$b$进制下的m,这样的话我们就可以直接统计加了几次$a$了,显然是个进制转化,照着二进制乱搞就可以了

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #define maxx 1001000
 5 #define ll long long
 6 #define inf 2000000000000000000
 7 using namespace std;
 8 ll S,T,a,b,base=1,m,ans=inf;
 9 ll ksm(ll a,int b)
10 {
11     ll ans=1;
12     while(b)
13     {
14         if(b&1)  ans*=a;
15         b=b>>1;  a*=a;
16     }
17     return ans;
18 }
19 int main()
20 {
21     scanf("%lld%lld%lld%lld",&S,&T,&a,&b);
22     for(int i=0;i<=64;++i)
23     {
24         if(base>T/S)  break;
25         ll cha=T-S*base;
26         if(cha%a==0)  m=cha/a;
27         else  {base*=b;  continue;}
28         ll sum=i;
29         for(int j=i;j>=0;--j)
30         {
31             ll mi=ksm(b,j);
32             sum+=m/mi;  m%=mi;
33         }
34         base*=b;  ans=min(ans,sum);
35     }
36     printf("%lld
",ans);
37     return 0;
38 }
View Code

T2

不知道为什么我像失忆了一般,我明明记得我打完了这道题,然而我残存的代码告诉我,我刚开始码他。。。。咕了

T3

他们发现了费用随特殊加热器的使用次数呈单谷函数,我们就可以愉快的开启三分的旅程,怎么$check$呢?考虑贪心,由于我们每次用普通加热器都会覆盖一段区间,所以用树状数组进行差分,首先预处理出来我如果在当前这个点使用普通加热器,最多能覆盖到哪一个点,$check$的时候从第一个点开始,如果还没有达到希望的能量,就使用加热器使他达到,顺带使可以和他一起使用加热器的点需要的能量值变少即可

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<bits/stdc++.h>
 6 #define maxn 100100
 7 #define int long long
 8 using namespace std;
 9 struct node{
10     int l,r;
11 }a[maxn];
12 int n,m,t,co_ba,maxx,l=0,r,head=1,minn=0x7fffffffffffffff;
13 int p[maxn],flag[maxn],c[maxn],to[maxn],sf[maxn];
14 bool cmp(const node &a,const node &b)
15 {
16     return a.l<b.l;
17 }
18 int lowbit(int x)
19 {
20     return x&(-x);
21 }
22 void add(int pos,int w)
23 {
24     for(;pos<=n;pos+=lowbit(pos))  c[pos]+=w;
25 }
26 int query(int pos)
27 {
28     int ans=0;
29     for(;pos>0;pos-=lowbit(pos))  ans+=c[pos];
30     return ans;
31 }
32 int check(int x)
33 {
34     memset(c,0,sizeof(c));
35     int sum=x*t;
36     for(int i=1;i<=n;++i)  sf[i]=max(1ll*0,p[i]-x);
37     for(int i=1;i<=n;++i)  add(i,sf[i]-sf[i-1]);
38     for(int i=1;i<=n;++i)
39     {
40         int ww=query(i);
41         if(ww<=0)  continue;
42         sum+=ww;  add(i,-ww);  add(to[i]+1,ww);
43     }
44     return sum;
45 }
46 signed main()
47 {
48     scanf("%lld%lld%lld",&n,&m,&t);
49     for(int i=1;i<=n;++i)  scanf("%lld",&p[i]);
50     for(int i=1;i<=m;++i)
51     {
52         scanf("%lld%lld",&a[i].l,&a[i].r);
53         for(int j=a[i].l;j<=a[i].r;++j)  flag[j]=1;
54     }
55     sort(a+1,a+m+1,cmp);
56     for(int i=1;i<=n;++i)
57         if(!flag[i])  maxx=max(maxx,p[i]);
58     for(int i=1;i<=n;++i)  {p[i]=max(1ll*0,p[i]-maxx);  r=max(r,p[i]);}
59     co_ba=t*maxx;  maxx=0;
60     for(int i=1;i<=n;++i)
61     {
62         while(a[head].l<=i&&head<=m)  {maxx=max(maxx,a[head].r);  head++;}
63         to[i]=maxx;
64     }
65     while(l+1<r)
66     {
67         int mid=(l+r)>>1;
68         int cost1=check(mid-1),cost2=check(mid);
69         minn=min(minn,cost1);  minn=min(minn,cost2);
70         if(cost1>=cost2)  l=mid;
71         else  r=mid;
72     }
73     co_ba+=minn;  printf("%lld
",co_ba);
74     return 0;
75 }
View Code

T4

说一下思路过程吧,一开始打了个暴力,枚举连接的两个端点直接求花费,然后只有30分,后来打了个小表发现一个端点确定之后另一个端点可以三分,就有了$T60$的好成绩,然后我就突然发现两个端点似乎可以三分套三分,但是由于中间平的地方太多,单谷不严格,所以三分本来就是死的,三分套三分就死透了,然后我惊讶的得知这道题数据水到随机化可$A$,然后我就$A$了。。。。。

 1 #include<iostream>
 2 #include<cstdio>
 3 #define maxn 100010
 4 using namespace std;
 5 struct node{
 6     int l,r;
 7 }q[maxn];
 8 int n,m,head,tail,ans=0x7fffffff;
 9 int check()
10 {
11     int maxx=0;
12     for(int i=1;i<=m;++i)
13     {
14         int len=q[i].r-q[i].l;
15         if(head>q[i].l&&tail<q[i].r)  len=min(len,head-q[i].l+q[i].r-tail);
16         else if(head<=q[i].l&&tail>=q[i].r)  len=min(q[i].r-q[i].l,q[i].l-head+tail-q[i].r);
17         else if(head>q[i].l&&tail>=q[i].r)  len=min(q[i].r-q[i].l,head-q[i].l+tail-q[i].r);
18         else if(head<=q[i].l&&tail<q[i].r)  len=min(q[i].r-q[i].l,q[i].l-head+q[i].r-tail);
19         maxx=max(maxx,len);
20         if(maxx>=ans)  return maxx;
21     }
22     return maxx;
23 }
24 int main()
25 {
26     scanf("%d%d",&n,&m);
27     for(int i=1;i<=m;++i)  scanf("%d%d",&q[i].l,&q[i].r);
28     if(m==1)  {printf("0
");  return 0;}
29     for(int i=1;i<=n;++i)
30     {
31         int l=i+2,r=n;
32         while(l+1<r)
33         {
34             int mid=(l+r)>>1;
35             head=i;  tail=mid-1;
36             int cost1=check();
37             head=i;  tail=mid;
38             int cost2=check();
39             ans=min(ans,cost1);  ans=min(ans,cost2);
40             if(cost1>=cost2)  l=mid;
41             else  r=mid;
42         }
43     }
44     printf("%d
",ans);
45     return 0;
46 }
View Code
原文地址:https://www.cnblogs.com/hzjuruo/p/11626675.html