2020.4.18--科大讯飞杯”第18届上海大学程序设计联赛春季赛暨高校网络友谊赛

链接:https://ac.nowcoder.com/acm/contest/5278/A
来源:牛客网

A.组队比赛
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 524288K,其他语言1048576K
64bit IO Format: %lld

题目描述

Compute, Cubercsl, SuperSodaSea, Ybmj 准备组队参加 "科大讯飞" 赞助的 CrossFire 比赛。
科大讯飞股份有限公司成立于1999年,是亚太地区知名的智能语音和人工智能上市企业。自成立以来,长期从事语音及语言、自然语言理解、机器学习推理及自主学习等核心技术研究并保持了国际前沿技术水平;积极推动人工智能产品研发和行业应用落地,致力让机器"能听会说,能理解会思考",用人工智能建设美好世界。
这场比赛需要两人一队组队参加,他们不知道怎么分组。已知他们的 CrossFire 分数分别为 a, b, c, d,现在想要把他们两两分为一队,使得他们的实力比较平均,也就是两队的实力差尽量小。
这里定义两队的实力差为每队的 CrossFire 分数之和的差值,现在他们想要知道这个实力差最小是多少。

输入描述:

仅一行,包含四个整数 a, b, c, d (1≤a,b,c,d≤36811 \leq a, b, c, d \leq 36811a,b,c,d3681),中间以空格分隔,分别表示四个人的 CrossFire 分数。

输出描述:

在一行输出一个整数,表示两个队伍实力差的最小值。
示例1

输入

复制
2 1 3 4

输出

 
示例2

输入

 

输出

#include<stdio.h>
int main()

{
    int s[5],t,sum;
    for(int i=0;i<4;i++)
    {
        scanf("%d",&s[i]);

    }
    for(int i=0;i<4;i++)
    {
        for(int j=i+1;j<4;j++)
        {
            if(s[i]>=s[j]){
                t=s[i];
                s[i]=s[j];
                s[j]=t;
            }
        }
    }
    sum=abs(s[0]+s[3]-s[1]-s[2]);
    printf("%d\n",sum);
}

B.每日一报

为了预防新型冠状病毒的侵袭,学校组织学生进行每日一报——自 2020 年 1 月 30 日 起至今,每位同学都必须上报自己的身体状况。为了简化问题,我们规定每日一报仅包含以下信息:
  • 报送日期:固定 8 位十进制数,格式为 YYYYMMDD ,如 20200312 代表 2020 年 3 月 12 日
  • 学号:固定 8 位十进制数,不必追溯其具体含义,如 17122490
  • 体温:保留一位小数的浮点数,单位为摄氏度,介于 35.0 至 45.0 之间,如 37.1。
作为学校数据库负责人,Lemon 需要对体温异常(不低于 38.0 摄氏度)的报送消息进行整理后向上级上报备案。具体整理规则如下:将报送日期作为第一关键字降序,将体温作为第二关键字降序,将学号作为第三关键字升序排序。即在整理完成后,任意两条报送记录都有如下关系:
  • 报送日期不一致的,则日期较近的在上,日期较久远的在下;
  • 报送日期一致体温不一致的,则体温高的在上,体温低的在下;
  • 报送日期和体温都一致的,则学号小的在上,学号大的在下。
你能帮助 Lemon 完成这个任务吗?

输入描述:

第一行包含一个整数 n (1≤n≤1001 \leq n \leq 1001n100),表示需要处理的报送记录。
接下来 n 行,每行代表一条报送记录。
每一条记录包含两个整数和一个浮点数,中间空格分隔,分别表示报送日期、学号和体温,格式如题目描述中所述
输入保证所有的报送日期是 2020 年 1 月 30 日至今(2020 年 4 月 18 日)的合法日期,同一个学号不会在同一天进行多次报送。

输出描述:

第一行输出一个整数 m,表示需要上报备案的记录数量。
接下来 m 行,每行为一条记录。
记录的顺序应符合题目要求,记录格式应与输入格式中所述记录格式保持一致。
示例1

输入

复制

输出

复制

备注:

Lemon 很清楚,他其实就是要执行 SQL 查询:SELECT * FROM REPORT WHERE(temperature>=38.0) ORDER BY date DESC, temperature DESC, studentID ASC;
#include<stdio.h>
struct student
{
    long long d;
    long long num;
    double t;
}s[110],b[110],k;
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
        scanf("%lld %lld %lf",&s[i].d,&s[i].num,&s[i].t);
    }
    for(int i=0;i<n;i++)
    {
       for(int j=i+1;j<n;j++)
       {
           if(s[i].d<s[j].d){
               k=s[i];
               s[i]=s[j];
               s[j]=k;
           }
           else if(s[i].d==s[j].d&&s[i].t<s[j].t)
           {
               k=s[i];
               s[i]=s[j];
               s[j]=k;
           }
           else if(s[i].d==s[j].d&&s[i].t==s[j].t&&s[i].num>s[j].num){
                k=s[i];
                s[i]=s[j];
                s[j]=k;
           }
       }
    }
    int sum=0,h=0;
    for(int i=0;i<n;i++)
    {
        if(s[i].t>=38.0){
            sum++;
            b[h++]=s[i];
        }
    }
    printf("%d\n",sum);
    for(int i=0;i<sum;i++){
        printf("%lld %lld %.1lf\n",b[i].d,b[i].num,b[i].t);
    }
}
3.C-最长非公子序列
Lemon 丢给你两个字母序列 s_1s1 和 s_2s2 ,并无情地交给了你一个奇怪的任务——求最长非公共子序列。
序列 a 是 b 的子序列,当且仅当从 b 中删除一些元素(可以是零个或所有)能得到 a。
例如:
我们可以通过从 "abcde" 中删除 "b" 和 "d" 得到 "ace",因此 "ace" 是 "abcde" 的子序列。
同理 "abcde","e" 和 空串 都是 "abcde" 的子序列;
但 "abdc" 不是 "abcde" 的子序列。
序列 c 是 s_1s1 和 s_2s2 的非公共子序列当且仅当它满足以下条件中的任何一个:
  • c 是 s_1s1 的子序列但不是 s_2s2 的子序列;
  • c 是 s_2s2 的子序列但不是 s_1s1 的子序列。
s_1s1 和 s_2s2 的非公共子序列可能有很多,你只需要求出其中长度最长的非公共子序列的长度。

输入描述:

第一行包含一个字符串 s_1s1 ,第二行包含一个字符串 s_2s2。 (1 \leq |s_1|, |s_2| \leq 50001s1,s25000)
输入保证 s_1s1s_2s2 均只包含小写字母。

输出描述:

在一行输出一个整数,表示最长非公共子序列的长度。
特别地,如果不存在非公共子序列,输出 -1 。
示例1

输入

复制
aba
abc

输出

复制
3
示例2

输入

复制
lemon
lemon

输出

复制
-1

备注:

对于第一个样例:非公共子序列有:"c","ba","bc","aba","abc",其中长度最大为 3。
对于第二个样例:找不到任何非公共子序列。
#include<bits/stdc++.h>
using namespace std;
int main(){
    string s1,s2;
    while(cin>>s1>>s2){
        if(s1.size()!=s2.size()){
            cout<<max(s1.size(),s2.size())<<endl;;
        }
        else if(s1!=s2){
            cout<<s1.size()<<endl;
        }
        else{
            cout<<"-1\n";
        }
    }
    return 0;
}

4.D-最大字符集

Cubercsl 很喜欢 01 字符串,就像“她喜欢大海”,这一天他想送她一个由 01 字符串组成的集合。
他自然是希望这个集合越多样化越大越好。所以他希望这个集合满足以下条件。
  • 每个字符串由 0 和 1 组成。
  • 每个字符串长度在 1 到 n 之间,且两两长度不同。
  • 集合中任何一个字符串都不是其他字符串的子串。
请你帮他找到满足他要求的最大的集合。
字符串 a 是 b 的子串当且仅当从 b 的头部和尾部删除一些字符(可以是零个或者所有)能得到的 a。

输入描述:

仅一行,包含一个整数 n(1 \leq n \leq 3001n300)。

输出描述:

第一行输出这个集合的大小 k。
接下来 k 行每行输出一个 01 字符串,表示这个集合的一个元素。
答案不唯一,任何符合要求的答案都会被判为正确。
示例1

输入

复制
1

输出

复制
1
1
示例2

输入

复制
5

输出

复制
4
00
110
1010
11111
#include<bits/stdc++.h>
using namespace std;
int main(){
    int n;
    while(cin>>n){
        if(n==1){
            cout<<1<<endl<<1<<endl;continue;
        }
        if(n==2){
            cout<<2<<endl<<0<<endl<<11<<endl;continue;
        }
        cout<<n-1<<endl;
        for(int i=2;i<=n;i++){
            for(int j=1;j<=i;j++){
                if(j==1||j==i)
                    cout<<"1";
                else
                    cout<<"0";
            }
            cout<<endl;
        }
    }
    return 0;
}

5.E-美味的序列

Cubercsl 喜欢吃序列,所以这一天不知道谁送了他一个序列,他非常快乐,想把他吃完。
序列的每一段自然也有好吃与不好吃的分别,他用数字标识了每个部分的美味度(可能是负的)。
现在,他可以从头或从尾部花费 1 秒吃掉这个序列的一个元素,并获得这个元素此时的美味度。但是,令他头疼的是,每经过 1秒,所有还没有被吃的部分的美味度会下降 1。
现在 Cubercsl 想知道,如果他按照合理的顺序吃完这个序列,他能获得的最大的美味度的和是多少?

输入描述:

第一行包含一个整数 n (1\leq n \leq 10 ^ 51n105) ,表示序列的长度。
第二行包含 n 个整数 a_1, a_2 , \ldots ,a_na1,a2,,an (0 \leq |a_i| \leq 10^90ai109),中间以空格分隔,分别表示这个序列每一部分的美味度。

输出描述:

在一行输出一个整数,表示吃完这个序列能获得的最大美味度的和。
示例1

输入

复制
3
3 2 3

输出

复制
5
示例2

输入

复制
1
-10

输出

复制
-10
#include <bits/stdc++.h>
#define LL long long
using namespace std;
LL ans;
int n,a[200050];
int main(){
    int i;
    cin >> n; for (i = 1; i <= n; ++i) cin >> a[i];
    for (i = 1; i <= n; ++i) ans += a[i];
    for (i = 1; i <= n; ++i) ans -= n-i;
    cout << ans << endl;
    return 0;
}

 

6.F-日期小助手

作为一个关心父母的孩子,Compute 会在每年的母亲节和父亲节为父母准备礼物。可是粗心的他却不记得它们的具体日期了。
已知:母亲节在每年 5 月的第 2 个周日;父亲节在每年 6 月的第 3 个周日。
现在你需要告诉他,下一个(不包括当天)母亲节或父亲节是在什么时候。

输入描述:

第一行包含一个整数 T (T \leq 100T100),表示测试数据的组数。
对于每组数据,包含三个整数 y, m, d,中间以空格分隔,分别表示今天的年、月、日。
输入保证是一个在公元 2000 年 1 月 1 日 到 2100 年 12 月 31 日间的合法日期。

输出描述:

对于每组数据,在一行输出下一个需要准备礼物的节日和日期。格式参考样例输出。
示例1

输入

复制
7
2000 1 1
2001 1 1
2002 1 1
2003 1 1
2020 1 1
2020 5 10
2020 6 21

输出

复制
Mother's Day: May 14th, 2000
Mother's Day: May 13th, 2001
Mother's Day: May 12th, 2002
Mother's Day: May 11th, 2003
Mother's Day: May 10th, 2020
Father's Day: June 21st, 2020
Mother's Day: May 9th, 2021

备注:

注意在冒号和逗号后面有一个空格。
#include<bits/stdc++.h>
using namespace std;
int main(){
    int t;
    cin>>t;
    while(t--){
        int y,m,d;
        cin>>y>>m>>d;
        int mo=14-((y-2000)+(y-2000)/4)%7;
        int fa=21-((y-1998)+(y-2000)/4+1)%7;
        if(y==2100){
            mo=9;fa=20;
        }
        //cout<<mo<<"&&"<<fa<<endl;
        if(m>=1&&m<=4){
            printf("Mother's Day: May %dth, %d\n",mo,y);continue;
        }
        if(m==5){
            if(d<mo)
                printf("Mother's Day: May %dth, %d\n",mo,y);
              else{
                if(fa!=21)
                    printf("Father's Day: June %dth, %d\n",fa,y);
                else
                    printf("Father's Day: June %dst, %d\n",fa,y);
            }
            continue;
        }
        if(m==6){
            if(d<fa){
                if(fa!=21)
                    printf("Father's Day: June %dth, %d\n",fa,y);
                else
                    printf("Father's Day: June %dst, %d\n",fa,y);
            }
            else{
                if(y==2100)
                    mo=8;
                else if(y==2099)
                  mo=9;
                else
                    mo=14-((y+1-2000)+(y+1-2000)/4)%7;
                printf("Mother's Day: May %dth, %d\n",mo,y+1);
            }
            continue;
        }
        if(m>=7&&m<=12){
            if(y==2100)
                mo=8;
            else if(y==2099)
                mo=9;
            else
                mo=14-((y+1-2000)+(y+1-2000)/4)%7;
            printf("Mother's Day: May %dth, %d\n",mo,y+1);
        }
        continue;
    }
    return 0;
}

7.G-血压游戏

Compute 有一棵 n 个点,编号分别为 1\sim n1n 的树,其中 s 号点为根。
Compute 在树上养了很多松鼠,在第 i 个点上住了 a_iai 个松鼠。
因为某些缘故,它们开始同时向根节点移动,但它们相当不安分,如果在同一个节点上,它们就会打起来,简单地来说以下事件会依序发生:
  • 如果一个节点上有 2 只或 2 只以上的松鼠,他们会打架,然后这个节点上松鼠的数量会减少 1;
  • 根节点的所有松鼠移动到地面,位于地面上的松鼠不会再打架;
  • 所有松鼠同时朝它们的父节点移动。
所有事件各自都在一瞬间完成,直至树上没有松鼠。
现在 Compute 想知道最终有多少只松鼠到达了地面。

输入描述:

第一行包含两个整数 n, s (1\leq n\leq 2 \cdot 10^51n2105, 1 \leq s \leq n1sn),中间以空格分隔,分别表示点的数量和根的编号。
第二行包含 n 个整数 a_1, a_2, \ldots a_na1,a2,an (0\leq a_i \leq 10^90ai109),中间以空格分隔,分别表示每个点上一开始的松鼠数量。
接下来 n-1 行,每行包含两个整数 u, v (u \neq vu=v, 1\leq u,v \leq n1u,vn),中间以空格分隔,表示 u 和 v 之间有一条边。
输入保证是一棵树。

输出描述:

在一行输出一个整数,表示最终到达地面的松鼠数量。
示例1

输入

复制
3 1
2 4 6
1 2
1 3

输出

复制
8
示例2

输入

复制
3 1
0 1 1
1 2
1 3

输出

复制
1

#include<bits/stdc++.h>
using namespace std;
#define M 200005
#define ll long long
vector<int>d[M];
int a[M],ln[M],tp[M],son[M],sz[M],fa[M],tot,dp[M],sk[M],fq[M];
struct h{
    int p,son1,son2;
}q[M];
ll val[M];
void dfs(int x,int f){
    dp[x]=dp[f]+1;sz[x]=1;fa[x]=f;ln[x]=++tot;
    for(int i=0;i<(int)d[x].size();++i){
        int v=d[x][i];
        if(v==f)continue;
        dfs(v,x);sz[x]+=sz[v];
        if(sz[v]>sz[son[x]])son[x]=v;
    }
}
void Dfs(int x,int top){
    tp[x]=top;
    if(son[x])Dfs(son[x],top);
    for(int i=0;i<(int)d[x].size();++i){
        int v=d[x][i];
        if(v==son[x]||v==fa[x])continue;
        Dfs(v,v);
    }
}
int Lca(int x,int y){
 while(tp[x]!=tp[y]){
        if(dp[tp[x]]>dp[tp[y]])x=fa[tp[x]];
        else y=fa[tp[y]];
    }
    return dp[x]>dp[y]?y:x;
}
bool cmp(int a,int b){
    if(dp[a]==dp[b])return ln[a]<ln[b];
    return dp[a]>dp[b];
}
int find(int x){return x==fq[x]?x:fq[x]=find(fq[x]);}
bool cmp1(h a,h b){
    if(dp[a.p]==dp[b.p])return ln[a.p]<ln[b.p];
    return dp[a.p]>dp[b.p];
}
int main(){
    int n,s;scanf("%d%d",&n,&s);
    for(int i=1;i<=n;++i)scanf("%d",&a[i]);
    for(int i=1,x,y;i<n;++i){
        scanf("%d%d",&x,&y);
        d[x].push_back(y);
        d[y].push_back(x);
    }dfs(s,0);Dfs(s,s);
    ll ans=0;int cnt=0;
    for(int i=1;i<=n;++i)if(a[i])sk[++cnt]=i;
    sort(sk+1,sk+cnt+1,cmp);
    for(int st=1;st<=cnt;st++){
        int en=st;
        while(en<=cnt&&dp[sk[en]]==dp[sk[st]])++en;
 int tot=0;en--;
        for(int i=st;i<=en;++i)fq[sk[i]]=sk[i],val[sk[i]]=a[sk[i]];
        if(st==en){
            ans+=max(1,a[sk[st]]-dp[sk[st]]);
            continue;
        }
        for(int i=st;i<en;++i){
            int lca=Lca(sk[i],sk[i+1]);
            q[++tot].p=lca;fq[lca]=lca;val[lca]=0;
            q[tot].son1=sk[i];q[tot].son2=sk[i+1];
        }sort(q+1,q+tot+1,cmp1);
        for(int i=1;i<=tot;++i){
            int x=find(q[i].son1),y=find(q[i].son2);
            ll w1=0,w2=0;
            if(x!=q[i].p)w1=max(1ll,val[x]-(dp[x]-dp[q[i].p]));if(y!=q[i].p)w2=max(1ll,val[y]-(dp[y]-dp[q[i].p]));
            val[q[i].p]+=w1+w2;fq[x]=fq[y]=q[i].p;
        }ans+=max(1ll,val[q[tot].p]-dp[q[tot].p]);
        st=en;
    }printf("%lld",ans);
}

 

8.H-纸牌游戏

Cubercsl 和 Oneday 在玩一个纸牌游戏。两个人手中都有 n 张数字牌,每张牌面上都包含 0 \sim 909 其中一个阿拉伯数字。
游戏规则是需要将手中的牌选出恰好 k 张,组成一个能被 3 整除的非负整数(不能含有多余前导零),组成的数大的获胜。
Cubercsl 自然是想取得胜利,所以他需要找到符合条件的最大的数。

输入描述:

第一行包含一个整数 T (T \leq 1000T1000),表示测试数据的组数。
对于每组测试数据,包含一个数字构成的串 s (1 \leq |s| \leq 10 ^ 51s105) 和一个整数 k (1 \leq k \leq |s|1ks∣),中间以空格分隔,分别表示 Cubercsl 手中的牌和要选出的牌的数量。
输入保证 \sum |s| < 10 ^ 6s<106。

输出描述:

对于每组测试数据,在一行输出一个整数,表示最大的能被 3 整除的数。特别地,如果无解,输出 -1。
示例1

输入

复制
9
998244353 1
998244353 2
998244353 3
998244353 4
998244353 5
998244353 6
998244353 7
998244353 8
998244353 9

输出

复制
9
99
993
9984
99852
998544
9985443
99854433
-1
示例2

输入

复制
5
99999999999999999999 1
99999999999999999999 2
99999999999999999999 3
99999999999999999999 4
99999999999999999999 5

输出

复制
9
99
999
9999
99999
#include<cstdio>
#include<cctype>
#include<queue>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<set>
#include<cmath>
using namespace std;
 
#define reg register
typedef long long ll;
#define rep(i,a,b) for(reg int i=a,i##end=b;i<=i##end;++i)
#define drep(i,a,b) for(reg int i=a,i##end=b;i>=i##end;--i)
 
#define pb push_back
template <class T> inline void cmin(T &a,T b){ ((a>b)&&(a=b)); }
template <class T> inline void cmax(T &a,T b){ ((a<b)&&(a=b)); }
 
char IO;
template<class T=int> T rd(){
    T s=0;
    int f=0;
    while(!isdigit(IO=getchar())) if(IO=='-') f=1;
    do s=(s<<1)+(s<<3)+(IO^'0');
    while(isdigit(IO=getchar()));
    return f?-s:s;
}
 
const int N=1e5+10;
int n,m;
char s[N],ans[N];
int cnt[10],c[3];
 
int Check(int n,int t){
    rep(i,0,2) c[i]=0;
    rep(i,0,9) c[i%3]+=cnt[i];
    // x+y=n-i
    // x<=c[2] ,y<=c[1]
    // 2x+y=t (mod 3)
    // x=n-i-y
    // 2n-2i-2y+y=t(mod 3)
    // 2n-y-2i=t(mod 3)
    // y=2n-2i-t (mod 3)
    int l0=max(0,n-c[1]-c[2]),r0=min(n,c[0]);
    drep(i,r0,max(l0,r0-4)) {
        int y=2*n-2*i-t;
        y=(y%3+3)%3;
        int l=max(0,n-i-c[2]),r=min(c[1],n-i); // y=的可行范围
        while(l%3!=y) l++;
        if(l<=r) return 1;
    }
    return 0;
}
 
int main(){
    rep(kase,1,rd()) {
        scanf("%s",s+1),n=strlen(s+1),m=rd();
        rep(i,0,9) cnt[i]=0;
rep(i,1,n) cnt[s[i]-'0']++;
        int fl=1,c=0;
        rep(i,1,m) {
            ans[i]=0;
            drep(j,9,0) if(cnt[j]) {
                cnt[j]--;
                int t=3-c-j;
                t=(t%3+3)%3;
                int fl=Check(m-i,t);
                if(fl) {
                    ans[i]=j+'0';
                    c=(c+j)%3;
                    break;
                }
                cnt[j]++;
            }
            if(!ans[i] || (i==1 && m>1 && ans[i]=='0') ) {
                fl=0;
                break;
            }
        }
        ans[m+1]=0;
        puts(!fl?"-1":ans+1);
    }
}

 

9.I-古老的打字机

Compute 在他的家里找到了一个打字机,他想要用这个打字机来打字,但是这个打字机实在是太古老了,以至于它根本就无法打出正确的内容。
给定 n 个由小写字母组成的字符串 s_1, s_2, \ldots s_ns1,s2,sn,每个字符串有一个价值 v_ivi
现在 Compute 会用这个打字机来打字,他会敲击打字机 m 次,得到字符串 t。其中,每次敲击会等概率地输入一个小写字母或者退格(Backspace)。
退格的作用是把当前得到的字符串的最后一个字符删除。特别地,如果当前字符串是空串,退格后仍为空串。
定义他最后所得到的字符串的价值为:每个串 s_isi 在得到的串 t 中的出现次数 c_ici 与 价值 v_ivi 的乘积。即 \displaystyle\sum_{k = 1} ^ n \sum_{i = 1} ^ {|t|} \sum_{j = i} ^ {|t|} v_k \cdot [s_k = \text{substr}(t, i, j)]k=1ni=1tj=itvk[sk=substr(t,i,j)]
其中 \text{substr}(t, i, j)substr(t,i,j) 表示 t 串从第 i 个字符到 第 j 个字符组成的子串;
艾佛森括号[\text{expr}] = \begin{cases} 1 & \text{expr 为真} \\ 0 & \text{expr 为假} \end{cases}[expr]={10expr 为真expr 为假
Compute 想要知道他得到的字符串价值的期望是多少。
可以证明这个期望的 27 ^ m27m 倍是一个整数,因此你只需要求出它的 27 ^ m27m 倍对 10 ^ 9 + 7109+7 取模后的结果。

输入描述:

第一行包含两个整数 n, m (1 \leq n, m \leq 10 ^ 31n,m103), 中间以空格分隔,分别表示字符串的个数和 Compute 的敲击次数。
接下来 n 行,每行包含一个由小写字母组成的字符串 s_isi (1 \leq |s_i| \leq 10 ^ 31si103)和一个整数 v_ivi (1 \leq v_i \leq 101vi10),中间以空格分隔,分别表示给定的字符串和它的价值。
输入保证 \sum |s_i| \leq 10 ^ 3si103。

输出描述:

在一行输出一个整数,表示 Compute 打出的随机字符串价值的期望的 27 ^ m27m 倍对 10 ^ 9 + 7109+7 取模后的结果。
示例1

输入

复制
1 1
a 1

输出

复制
1
示例2

输入

复制
2 2
a 1
aa 2

输出

复制
55
示例3

输入

复制
3 3
a 1
aa 2
aaa 3

输出

复制
2242

备注:

对于第一个样例,共有 27 种情况,只有 a 具有 1 的价值,因此答案为 \frac{1}{27}271,输出 1;
对于第二个样例,共有 27 ^ 2272 种情况,其中 aa 的价值为 4,ab, ba ... az, za 的价值为 1,a (退格 + a)的价值为 1,因此答案为 \frac{55}{27 ^ 2}27255,输出 55。
#include <bits/stdc++.h>
using namespace std;
long long dp[10000][10000]={0};
long long cans[10000]={0};
const long long mod=1e9+7;
long long gcd(long long a,long long b,long long &x,long long &y)
{
    if (b)
    {
        long long c=gcd(b,a%b,x,y);
        long long t=x;
        x=y;
        y=t-a/b*y;
        return c;     
    }
    else
    {
        x=1,y=0;
        return a;
    }
}
long long inv(long long a)
{
    long long x,y,d=gcd(a,mod,x,y);
    if(d==1)
        if(x%mod<=0)return x%mod+mod;
        else return x%mod;
    else return -1;
}
long long qpow(long long a,long long b) {long long res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
int main()
{
    long long l,q;
    cin>>q>>l;
    dp[0][0]=1;
    dp[0][1]=0;
    for (long long i=1;i<=l;i++)
    {
        dp[i][0]=(dp[i-1][0]+dp[i-1][1])%mod;
        for(long long j=1;j<i;j++) dp[i][j]=(dp[i-1][j-1]*26+dp[i-1][j+1])%mod;
        dp[i][i]=(dp[i-1][i-1]*26)%mod;
    }
    for (long long i=1;i<=l;i++)
        for(long long j=i;j<=l;j++)
            cans[i]=(cans[i]+dp[l][j]*(j-i+1)%mod*inv(qpow(26,i))%mod)%mod;
    long long ans=0;
    while(q--)
    {
        string s;long long score;
        cin>>s>>score;
        ans=(ans+cans[s.size()]*score%mod)%mod;
    }
    cout<<(ans+mod)%mod<<endl;
    return 0;
}

 

 

10.J-能到达吗

链接:https://ac.nowcoder.com/acm/contest/5278/J
来源:牛客网

Xiaowang 身处一张 n×mn \times mn×m 大小的地图中。地图最左上角的坐标为 (1, 1),最右下角的坐标为 (n, m)。地图中有 k 个障碍物,每个障碍物放的位置由坐标表示,障碍物占用坐标所在的一格。除了障碍物,地图中都是空地。
Xiaowang 可以在相邻的空地间自由穿梭,但不可以走出地图,也不可以走到障碍物上。我们称坐标 (xi,yi)(x_i, y_i)(xi,yi) 和坐标 (xj,yj)(x_j, y_j)(xj,yj) 是相邻的,当且仅当 ∣xi−xj∣+∣yi−yj∣=1\left| x_i - x_j \right| + \left| y_i - y_j \right| = 1xixj+yiyj=1。
Xiaowang 想知道有多少无序对 {(x1,y1),(x2,y2)}\{(x_1, y_1), (x_2, y_2)\}{(x1,y1),(x2,y2)} 满足:他可以从其中一个点出发并且能够到达另一个点。
由于答案可能很大,因此你只需要求出它答案对 109+710 ^ 9 + 7109+7 取模后的结果。

输入描述:

第一行包含一个整数 T (T≤104T \leq 10 ^ 4T104) 表示测试数据的组数。 对于每组测试数据:
第一行包含两个整数 n, m (1≤n,m≤2⋅1051 \leq n,m \leq 2 \cdot 10 ^ 51n,m2105),中间以空格分隔,分别表示地图行数和列数。
第二行包含一个整数 k (0≤k≤1060 \leq k \leq 10 ^ 60k106),表示障碍物的数量。
接下来 k 行,每行包含两个整数 xix_ixiyiy_iyi (1≤xi≤n1 \leq x_i \leq n1xin , 1≤yi≤m1 \leq y_i \leq m1yim,∀i≠j,xi≠xj∨yi≠yj\forall i \neq j, x_i \neq x_j \lor y_i \neq y_ji=j,xi=xjyi=yj),中间以空格分隔,表示第 i 个障碍物的坐标。
输入保证 ∑k≤106\sum k \leq 10 ^ 6k106。

输出描述:

对于每组测试数据,在一行输出一个整数,表示点对的数量对 109+710 ^ 9 + 7109+7 取模后的结果。
示例1

输入

复制
2
2 2
1
1 2
200000 200000
0

输出

复制
6
39060

备注:

对于第一个样例:
如果用 0 表示空地,用 1 表示障碍物,则地图可以表示为:
(0100)\begin{pmatrix} 0 & 1\\ 0 & 0 \end{pmatrix}(0010)
符合题目要求的点对有 6 个:
{(1, 1), (1, 1)} , {(2, 1), (2, 1)} , {(2, 2), (2, 2)} , {(1, 1), (2, 1)} , {(1, 1), (2, 2)} , {(2, 1), (2, 2)}。
对于第二个样例:
符合题目要求的点对有 (200 00021)+(200 00022)=80 000 000 002×1010{{200\,000 ^ 2}\choose {1}} + {{200\,000 ^ 2} \choose {2}} = 80\,000\,000\,002 \times 10 ^ {10}(12000002)+(22000002)=80000000002×1010 个。
109+710 ^ 9 + 7109+7 取模后结果为 39 06039\,06039060。

注意起点和终点同样应该是空地,否则 Xiaowang 就会被困在障碍物中。
#include <bits/stdc++.h>
#define LL long long
#define int long long
using namespace std;
template <typename T> void read(T &x){
    x = 0; char ch = getchar();
    while (!isdigit(ch)) ch = getchar();
    while (isdigit(ch)) x = x * 10 + ch - '0',ch = getchar();
}
const int K = 2000050,N = 200050,P = 1e9 + 7;
int n,m,k;
struct Point{ int x,y; Point(int xx=0,int yy=0){ x=xx,y=yy; } }a[K];
vector<int>G[N];
inline bool cmpxp(Point A,Point B){ return (A.x != B.x) ? (A.x < B.x) : (A.y < B.y); }
int fa[K<<1],size[K<<1];
inline int Find(int x){ return x == fa[x] ? x : fa[x] = Find(fa[x]); }
inline void Merge(int x,int y){ if ((x=Find(x))==(y=Find(y))) return; fa[y] = x,size[x] = (size[x]+size[y])%P; }
 
struct Mat{ int xl,xr,yl,yr; }ma[K<<1]; int cntid;
inline bool cmpx(Mat A,Mat B){ return (A.xl != B.xl) ? (A.xl < B.xl) : (A.yl < B.yl); }
int vx[K],lv; int vis[N];
 
int lb,b[N],bl[N],br[N],fl[N],fr[N];
int lc,c[N],cl[N],cr[N];
inline bool check(int l1,int r1,int l2,int r2){ return max(l1,l2) <= min(r1,r2); }
inline void work(int l1,int r1,int l2,int r2){
    int i,j,cll,crr,L,R,Mid;
    lb = r1-l1+1; for (i = l1; i <= r1; ++i) b[i-l1+1] = i;
    lc = r2-l2+1; for (i = l2; i <= r2; ++i) c[i-l2+1] = i;
    for (i = 1; i <= lb; ++i) bl[i] = ma[b[i]].yl,br[i] = ma[b[i]].yr,fl[i] = -1,fr[i] = -2;
for (i = 1; i <= lc; ++i) cl[i] = ma[c[i]].yl,cr[i] = ma[c[i]].yr;
    for (i = 1; i <= lb; ++i) if (check(bl[i],br[i],cl[1],cr[lc])){
        fl[i] = 1,L = 1,R = lc;
        while (L <= R){
            Mid = L+R>>1; if (cr[Mid] < bl[i]) fl[i] = Mid + 1,L = Mid + 1; else R = Mid - 1;
        }
        L = fl[i],R = lc,fr[i] = fl[i]-1;
        while (L <= R){
            Mid = L+R>>1; if (cl[Mid] <= br[i]) fr[i] = Mid,L = Mid + 1; else R = Mid - 1;
        }
        if (!check(fl[i],fr[i],1,lc)) bl[i] = -1,br[i] = -2;
        else if (!check(bl[i],br[i],cl[fl[i]],cr[fl[i]])) bl[i] = -1,br[i] = -2;
        else if (!check(bl[i],br[i],cl[fr[i]],cr[fr[i]])) bl[i] = -1,br[i] = -2;
        else Merge(b[i],c[fl[i]]);
    }
    int lst = -1,nl = -1,nr = -2;
    for (i = 1; i <= lb; ++i) if (fl[i] <= fr[i]){
        if (lst != -1 && check(nl,nr,fl[i],fr[i])) Merge(lst,b[i]),nr = fr[i];
        else{
            if (lst != -1) for (j = nl; j <= nr; ++j) Merge(lst,c[j]);
            lst = b[i],nl = fl[i],nr = fr[i];
        }
    }
    if (lst != -1) for (i = nl; i <= nr; ++i) Merge(lst,c[i]);
}
inline void solve(){
    int i,j,v,t;
    read(n),read(m),read(k),cntid = 0;
    for (i = 1; i <= k; ++i) read(a[i].x),read(a[i].y);
    sort(a+1,a+k+1,cmpxp);
vx[lv=1]=0;
    for (i = 1; i <= k; ++i) G[a[i].x].push_back(a[i].y),vx[++lv] = a[i].x,vis[a[i].x] = 0;
    vx[++lv] = n+1;
    sort(vx+1,vx+lv+1);
    cntid = 0;
    for (i = 1; i < lv; ++i) if (vx[i] + 1 < vx[i+1]){
        ++cntid;
        ma[cntid].yl = 1,ma[cntid].yr = m;
        ma[cntid].xl = vx[i]+1,ma[cntid].xr = vx[i+1]-1;
    }
    for (i = 1; i <= k; ++i) if (!vis[a[i].x]){
        t = a[i].x; vis[t] = 1;
        G[t].push_back(0),G[t].push_back(m+1); sort(G[t].begin(),G[t].end());
        for (j = 0; j < G[t].size()-1; ++j) if (G[t][j] + 1 < G[t][j+1]){
            ++cntid;
            ma[cntid].yl = G[t][j]+1,ma[cntid].yr = G[t][j+1]-1;
            ma[cntid].xl = ma[cntid].xr = t;
        }
        G[t].clear();
    }
    sort(ma+1,ma+cntid+1,cmpx);
    for (i = 1; i <= cntid; ++i)
        fa[i] = i,size[i] = 1ll * (ma[i].xr-ma[i].xl+1) * (ma[i].yr-ma[i].yl+1) % P;
    int nl = 1,nr = 1,nxl = ma[1].xl,ll = -1,lr = -1;
    for (i = 2; i <= cntid; ++i){
        if (nxl == ma[i].xl){ nr = i; continue; }
        if (ll != -1 && abs(ma[ll].xr-ma[nl].xl) == 1) work(ll,lr,nl,nr);
        ll = nl,lr = nr; nl = nr = i,nxl = ma[i].xl;
    }
    if (ll != -1 && abs(ma[ll].xr-ma[nl].xl) == 1) work(ll,lr,nl,nr);
for (i = 1; i <= k; ++i) G[a[i].x].clear(),vis[a[i].x] = 0;
    int ans = 0;
    for (i = 1; i <= cntid; ++i) if (fa[i] == i) ans = (ans + 1ll * size[i] * (size[i]+1)/2 % P) % P;
    cout << (ans+P)%P << '\n';
}
 
signed main(){ int T; read(T); while (T--) solve(); return 0; }

 

 

11.K-迷宫

链接:https://ac.nowcoder.com/acm/contest/5278/K
来源:牛客网

SuperSodaSea 在玩一个走迷宫的游戏。迷宫是一个大小为 n×mn \times mn×m 的矩阵,从上到下依次给行编号为 0,1,…n−10, 1, \ldots n - 10,1,n1,从左到右依次给列编号为 0,1,…,m−10, 1, \ldots, m - 10,1,,m1。
游戏规则很简单:从起点出发,每步操作可以移动到上、下、左、右四个方向的空地上,直到终点。
为了增加游戏的难度,在这个游戏中,从起点到终点并不一定会有直接的通路。当然,相对应地,玩家可以使用名为“穿越”的技能:从一块空地移动到距离至多为 d 另一片空地上(起点和终点也视为空地),无论中间是否有障碍。
在使用技能时的距离是指“切比雪夫距离”,即如果从 (x1,y1)(x_1, y_1)(x1,y1) 穿越到 (x2,y2)(x_2, y_2)(x2,y2) 需要满足 max⁡{∣x1−x2∣,∣y1−y2∣}≤d\max\{|x_1 - x_2|, |y_1 - y_2|\} \leq dmax{x1x2,y1y2}d。“穿越”只能最多使用一次,使用时算一步操作。
现在你需要帮 SuperSodaSea 计算出给定的迷宫,他最少需要多少步才能到达终点,并给出一个方案。

输入描述:

第一行包含 3 个整数 n, m, d (1≤n,m≤2 0001 \leq n, m \leq 2\,0001n,m2000, 0≤d≤2 0000 \leq d \leq 2\,0000d2000),中间以空格分隔,分别表示地图的行数、列数和穿越的最大距离。
接下来 n 行,每行包含一个长度为 m 的字符串,表示地图。
其中,. 表示空地,X 表示障碍,S 表示起点,T表示终点。
输入保证有且仅有一个起点和一个终点。

输出描述:

第一行输出一个整数 t 表示最少所需要的步骤。
接下来 t + 1 行,每行输出两个整数 xi,yix_i, y_ixi,yi,中间以空格分隔, 表示每一步所经过的坐标。其中,第一行和最后一行应分别对应起点和终点。
特别地,如果没有可以走到终点的方案,则在一行输出 -1。
答案不唯一,任何符合要求的答案都会被判为正确。
示例1

输入

复制
5 7 2
SXX....
.XX.XX.
.XXXXX.
.XX.XX.
....XXT

输出

复制
17
0 0
1 0
2 0
3 0
4 0
4 1
4 2
4 3
3 3
1 3
0 3
0 4
0 5
0 6
1 6
2 6
3 6
4 6
示例2

输入

复制

输出

复制
#include<cstdio>
#include<cctype>
#include<queue>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<set>
#include<cmath>
#include<cassert>
using namespace std;
 
#define reg register
typedef long long ll;
#define rep(i,a,b) for(reg int i=a,i##end=b;i<=i##end;++i)
#define drep(i,a,b) for(reg int i=a,i##end=b;i>=i##end;--i)
 
#define pb push_back
template <class T> inline void cmin(T &a,T b){ ((a>b)&&(a=b)); }
template <class T> inline void cmax(T &a,T b){ ((a<b)&&(a=b)); }
 
char IO;
template<class T=int> T rd(){
    T s=0;
    int f=0;
    while(!isdigit(IO=getchar())) if(IO=='-') f=1;
    do s=(s<<1)+(s<<3)+(IO^'0');
    while(isdigit(IO=getchar()));
    return f?-s:s;
}
const int N=2e3+10,INF=1e9+10;
 
int n,m,d,sx,sy,fx,fy;
char s[N][N];
pair <int,int> pre1[N][N],pre2[N][N],pre3[N][N]; // 记录了转移方案
int dis[N][N];
queue <pair <int,int> > que; // bfs序列
const int z[5][4]={{-1,0},{1,0},{0,1},{0,-1}};
 
struct Node{
    int x,y,d;
    bool operator < (const Node __) const {
        return d<__.d;
    }
    bool operator > (const Node __) const {
        return d>__.d;
    }
}A[N][N<<1],B[N*N]; //x,y决策位置,d为决策权值
int cnt;
Node Q[N];
int L,R;
int ansx[N*N*2],ansy[N*N*2],ansc;
 
 
int main(){
    n=rd(),m=rd(),d=rd();
    rep(i,1,n) scanf("%s",s[i]+1);
    rep(i,1,n) rep(j,1,m) if(s[i][j]=='S') sx=i,sy=j;
    rep(i,1,n) rep(j,1,m) if(s[i][j]=='T') fx=i,fy=j;
//三步转移
    //Part1
    rep(i,1,n) rep(j,1,m) dis[i][j]=INF;
    que.push(make_pair(sx,sy)),dis[sx][sy]=0;
    while(!que.empty()) {
        int x=que.front().first,y=que.front().second; que.pop();
        rep(i,0,3) {
            int x1=x+z[i][0],y1=y+z[i][1];
            if(dis[x1][y1]==INF && s[x1][y1]!='X') dis[x1][y1]=dis[x][y]+1,pre1[x1][y1]=make_pair(x,y),que.push(make_pair(x1,y1));
        }
    }
 
 
    //Part2
    rep(i,1,n) {
        L=1,R=0;
        rep(j,1,m+d) {
            while(L<=R && Q[L].y<j-d*2) ++L;
            if(dis[i][j]<INF && j<=m) {
                Node t=(Node){i,j,dis[i][j]};
                while(L<=R && Q[R]>t) --R;
                Q[++R]=t;
            }
            if(L<=R) A[i][j]=Q[L];
        }
    }
    rep(j,1,m) {
        int ry=j+d,now=0;
        L=1,R=0;
 rep(i,1,n) {
            int lx=max(1,i-d),rx=min(n,i+d);
            while(L<=R && Q[L].x<lx) ++L;
            while(now<rx) {
                ++now;
                if(!A[now][ry].x) continue
                while(L<=R && Q[R]>A[now][ry]) R--;
                Q[++R]=A[now][ry];
            }
            if(s[i][j]!='X' && L<=R && Q[L].x && Q[L].d+1<dis[i][j]) dis[i][j]=Q[L].d+1,pre2[i][j]=make_pair(Q[L].x,Q[L].y);
        }
    }
 
    //Part3
    rep(i,1,n) rep(j,1,m) B[++cnt]=(Node){i,j,dis[i][j]};
    sort(B+1,B+cnt+1);
    rep(i,1,cnt) que.push(make_pair(B[i].x,B[i].y));
    while(!que.empty()) {
        int x=que.front().first,y=que.front().second; que.pop();
        rep(i,0,3) {
            int x1=x+z[i][0],y1=y+z[i][1];
            if(dis[x1][y1]>dis[x][y]+1 && s[x1][y1]!='X') dis[x1][y1]=dis[x][y]+1,pre3[x1][y1]=make_pair(x,y),que.push(make_pair(x1,y1));
        }
    }
 
    //输出方案
    if(dis[fx][fy]==INF) return puts("-1"),0;
    int x=fx,y=fy;
    ansx[++ansc]=x,ansy[ansc]=y;
    while(pre3[x][y].first) {
 auto t=pre3[x][y];
        x=t.first,y=t.second;
        ansx[++ansc]=x,ansy[ansc]=y;
    }
    if(pre2[x][y].first) {
        auto t=pre2[x][y];
        x=t.first,y=t.second;
        ansx[++ansc]=x,ansy[ansc]=y;
    }
    while(pre1[x][y].first) {
        auto t=pre1[x][y];
        x=t.first,y=t.second;
        ansx[++ansc]=x,ansy[ansc]=y;
    }
    printf("%d\n",ansc-1);
    drep(i,ansc,1) printf("%d %d\n",ansx[i]-1,ansy[i]-1);
}

 

12.动物森友会

链接:https://ac.nowcoder.com/acm/contest/5278/L
来源:牛客网

Compute 最近开始玩动物森友会了。
这个游戏的时间与现实时间是同步的(一周有 7 天),而一些特定事件只会在一周的某些天解锁。
我们假设有 n 个不同的事件,而每个事件都会给予不同的材料,并且每个事件只会在一周中的特定几天开放,在开放的时间内可以完成多次。但由于 Compute 要参加训练,他每天并没有多少时间玩游戏,所以他每天最多只能完成 e 次事件。
现在 Compute 想做出一件非常稀有的道具——高达,并且他计算出了他收集齐所有材料需要完成每一种事件的次数。
假设现在 Compute 从周一开始玩这个游戏,他最少需要经过几天(包括不玩游戏的日子)才能造出高达?

输入描述:

第一行包含 2 个整数 n, e (1≤n≤1 0001 \leq n \leq 1\,0001n1000, 1≤e≤1001 \leq e \leq 1001e100),中间以空格分隔,分别表示不同事件的数量和 Compute 一天能完成的事件次数。
接下来 n 行,每行包含 mi+2m_i + 2mi+2 个整数 cic_ici, mim_imi, ai1,ai2,…,aimia_{i_1}, a_{i_2}, \ldots, a_{i_{m_i}}ai1,ai2,,aimi (1≤ci≤1051 \le c_i \le 10 ^ 51ci105, 1≤mi≤71 \leq m_i \leq 71mi7, 1≤aij≤71 \leq a_{i_j} \leq 71aij7, ∀j≠k,aij≠aik\forall j\ne k, a_{i_j}\ne a_{i_k}j=k,aij=aik),中间以空格分隔,分别表示事件 i 需要完成的次数、事件开放的天数和事件 i 在一周中的哪些时间会开放。

输出描述:

在一行输出一个整数,表示 Compute 造出高达的最少天数。
示例1

输入

复制

输出

复制

备注:

可以按如下方案进行:
第 1 天(周一):事件 1 和 3 各一次;
第 2 天(周二):事件 2 和 3 各一次;
第 3 天(周三):事件 1 和 4 各一次;
第 4 天(周四):事件 2 和 4 各一次;
第 5 天(周五):事件 5 两次。
正好 5 天即可完成。
#include <bits/stdc++.h>
#define int long long
using namespace std;
template <typename T> void read(T &x){
    x = 0; int f = 1; char ch = getchar();
    while (!isdigit(ch)) {if (ch == '-') f = -1; ch = getchar();}
    while (isdigit(ch)) {x = x * 10 + ch - '0'; ch = getchar();}
    x *= f;
}
inline void write(int x){if (x > 9) write(x/10); putchar(x%10+'0'); }
 
const int N = 1050,M = 7+2,V = N + 50,E = 200050;
int To[E],Ne[E],Flow[E],He[V],_k = 1;
inline void add(int x,int y,int flow){
    ++_k; To[_k] = y,Flow[_k] = flow,Ne[_k] = He[x],He[x] = _k;
    ++_k; To[_k] = x,Flow[_k] = 0,Ne[_k] = He[y],He[y] = _k;
}
inline void init(){ _k = 1;memset(He,0,sizeof(He)); }
int n,K;
int qwq[7+5],sumn;
int need[N],len[N],a[N][M];
 
int S,T,Now[V];
inline void initNow(){
    int i;
    for (i = 1; i <= T; ++i) Now[i] = He[i];
}
int dis[V],Q[V],ql,qr;
inline bool Bfs(){
 int i,x,y,p;
    for (i = 1; i <= T; ++i) dis[i] = 0;
    dis[S] = 1; Q[ql=qr=1]=S;
    while (ql <= qr){
        x = Q[ql],++ql;
        for (p = He[x]; p ; p = Ne[p]) if (Flow[p] && !dis[y=To[p]])
            dis[y] = dis[x] + 1,Q[++qr] = y;
    }
    return dis[T] > 0;
}
inline int Dfs(int x,int flow){
    if (!flow || x == T) return flow;
    int y,p,f,rest = flow;
    for (p = Now[x]; p ; p = Ne[p]){
        Now[x] = p;
        if (Flow[p] && dis[y=To[p]] == dis[x] + 1){
            f = Dfs(y,min(rest,Flow[p]));
            rest -= f,Flow[p] -= f,Flow[p^1] += f;
            if (!rest) return flow;
        }
    }
    dis[x] = -1;
    return flow - rest;
}
inline int Dinic(){
    int sum = 0;
    while (Bfs()) initNow(),sum += Dfs(S,sumn);
    return sum;
}
inline bool check(int days){
    int i,j;
    init();
    S = n+8,T = n+9;
    for (i = 1; i <= 7; ++i){
        qwq[i] = min(1ll * sumn,1ll * K * ( days / 7 + ( (i<=days%7) ? 1 : 0) ));
    }
    for (i = 1; i <= 7; ++i) add(i,T,qwq[i]);
    for (i = 1; i <= n; ++i){
        add(S,i+7,need[i]);
        for (j = 1; j <= len[i]; ++j) add(i+7,a[i][j],need[i]);
    }
    return Dinic() >= sumn;
}
 
signed main(){
    int i,j;
    read(n),read(K);
    sumn = 0;
    for (i = 1; i <= n; ++i){
        read(need[i]),read(len[i]);
        sumn += need[i];
        for (j = 1; j <= len[i]; ++j) read(a[i][j]);
    }
    int L = 0,R = 2000000000,Mid,Ans = 2000000000;
    while (L <= R){
        Mid = L+R>>1; if (check(Mid)) Ans = Mid,R = Mid - 1; else L = Mid + 1;
    }
    cout << Ans << '\n';
  return 0;
}

 

posted @ 2020-04-25 20:03  西瓜0  阅读(901)  评论(0)    收藏  举报