2019正睿CSP-S模拟赛十连测day7

2019正睿CSP-S模拟赛十连测day7

今天上午刚考完初赛,全员90+,就只有我是80(有可能80-?),慌得一匹,洛谷讨论一面又有一堆人估分比我高,还问有没有救,我原地自闭。教练说一星期后才能出分数线,那我这一个星期看来都要在自闭中度过了。

今天这场比赛就是在自闭中度过的,感觉没能很好地集中精力做题,一直在想初赛(也许集中精力也不能打上去?),最后的分数是

100+50+0(期望10)=150(rank=25)

T1感觉还是比较送的,乱搞之中出正解,玩了玩搞了搞终于在一个小时之后弄了出来,T2有一个一眼的递归式,写了个记忆化上去,T3一看根本连思路都没有,直接自爆了。

link to this contest

A. dls的生日礼物

  • 首先判掉无解的情况,就是存在三个区间互相有交
  • 现在对于任意一个位置都最多只会被两个区间覆盖,每个联通块只能相间分布,两种情况,并且与其它联通块相独立,于是答案就是$2^{联通块个数}$
 1 #include<bits/stdc++.h>
 2 #define FOR(i,a,b) for (register int i=(a);i<=(b);i++)
 3 #define For(i,a,b) for (register int i=(a);i>=(b);i--)
 4 #define mem(i,j) memset(i,j,sizeof(i))
 5 #define GO(u) for (register int j=f[u];j!=-1;j=nxt[j])
 6 #define fi first
 7 #define se second
 8 #define pb push_back
 9 #define MP make_pair
10 #define pii pair<int,int>
11 using namespace std;
12 typedef long long ll;
13 const int N=2e6+5;
14 const int mod=998244353;
15 int n,ans=1,a[N],len=0,t[N],maxr;
16 struct data
17 {
18     int l,r;
19 }f[N];
20 bool cmp(const data x,const data y) 
21 {
22     if (x.l==y.l) return x.r<y.r;
23     return x.l<y.l;
24 }
25 inline int read()
26 {
27     int x=0,f=1;
28     char c=getchar();
29     while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
30     while (c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-'0';c=getchar();}
31     return f*x;
32 }
33 inline void write(int x)
34 {
35     if (x<0) putchar('-'),x=-x;
36     if (x>9) write(x/10);
37     putchar(x%10+'0');
38     return;
39 }
40 inline int val(int x) {return lower_bound(a+1,a+len+1,x)-a;}
41 inline void no()
42 {
43     printf("0
");
44     exit(0);
45 }
46 inline int pan()
47 {
48     FOR(i,1,n) t[f[i].l]++,t[f[i].r]--;
49     FOR(i,1,len) t[i]+=t[i-1];
50     FOR(i,1,len) if (t[i]>2) return 1;
51     return 0;
52 }
53 int main()
54 {
55 //    freopen("data.in","r",stdin);
56 //    freopen("myans.out","w",stdout);
57     n=read();
58     FOR(i,1,n) f[i].l=read(),f[i].r=read(),a[++len]=f[i].l,a[++len]=f[i].r;
59     sort(a+1,a+len+1);
60     len=unique(a+1,a+len+1)-a-1;
61     FOR(i,1,n) f[i].l=val(f[i].l),f[i].r=val(f[i].r);
62     if (pan()) no();
63     sort(f+1,f+n+1,cmp);
64     maxr=0;
65     FOR(i,1,n)
66     {
67         if (f[i].l>=maxr) ans=1LL*ans*2%mod,maxr=f[i].r;
68         else maxr=max(maxr,f[i].r);
69     }
70     write(ans);
71     return 0;
72 }
73 /*
74 9
75 14 18
76 13 15
77 16 17
78 1 3
79 2 5
80 4 7
81 6 8
82 9 10
83 11 12
84 */
View Code

B. dls的生日宴会

这题首先有下面这个式子,设$f(n)$为剩下$n$个人时的答案

$$f(n)=min {a*k+b+f(lceil frac{n}{k+1} ceil)}$$

直接记忆化搜一下就行了,试着把决策点输出一下发现每一轮的$k$是单调的(还没发现可以只取两个数)

  • 游戏最多进行$lceil logn ceil$次,我们枚举$m$表示游戏进行的次数,存在一组$k_i$使得游戏成功当且仅当$prod_{i=1}^m (k_i+1) ge n$
  • 然后我们又发现当我们在满足上式成立时,我们希望$sum k_i$尽可能小,由均值不等式得,我们希望$k_i$尽可能接近,于是必定存在一组最优解使得所有$k_i$取到相邻的两个取值
  • 枚举$m$,给$n$开$m$次方,再快速幂回去,看看大的那个值需要多少个,复杂度$O(T log^2n)$
 1 #include<bits/stdc++.h>
 2 #define FOR(i,a,b) for (register ll i=(a);i<=(b);i++)
 3 #define For(i,a,b) for (register ll i=(a);i>=(b);i--)
 4 #define mem(i,j) memset(i,j,sizeof(i))
 5 #define GO(u) for (register ll j=f[u];j!=-1;j=nxt[j])
 6 #define fi first
 7 #define se second
 8 #define pb push_back
 9 #define MP make_pair
10 #define pii pair<ll,ll>
11 using namespace std;
12 typedef long long ll;
13 const ll inf=1e18;
14 ll t,n,a,b,ans;
15 inline ll read()
16 {
17     ll x=0,f=1;
18     char c=getchar();
19     while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
20     while (c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-'0';c=getchar();}
21     return f*x;
22 }
23 inline void write(ll x)
24 {
25     if (x<0) putchar('-'),x=-x;
26     if (x>9) write(x/10);
27     putchar(x%10+'0');
28     return;
29 }
30 inline ll qpow(ll x,ll y)
31 {
32     ll ret=1;
33     while (y)
34     {
35         if (y&1) ret=ret*x;
36         y>>=1;
37         x=x*x;
38     }
39     return ret;
40 }
41 int main()
42 {
43     t=read();
44     while (t--)
45     {
46         ans=inf;
47         n=read(),b=read(),a=read();
48         if (n==1) {printf("0
");continue;}
49         FOR(i,1,30)
50         {
51             ll tmp1=pow(n,1.0/i);
52             ll tmp2=qpow(tmp1,i);
53             ll k=(tmp1-1)*i;
54             while(tmp2<n) tmp2/=tmp1,tmp2*=tmp1+1,k++;
55             ans=min(ans,a*k+b*i);
56         }
57         write(ans),putchar('
');
58     }
59     return 0;
60 }
View Code
原文地址:https://www.cnblogs.com/C-S-X/p/11706199.html