Codeforces 水题选刷

翻译会给出在代码中

Ctrl+F点开网页搜索,直接查题号即可

有一些很棒的题我会单独拿出来写题解的,特别水的题就不做了嘻嘻嘻

Codeforces 938C

/*
题解:
给定两个正整数n,m(m≤n),对于一个n阶0-1方阵,
其任意m阶子方阵中至少有一个元素“0”,则可以求解这个方阵中的“1”的最大数目。现求解这个问题的逆向问题:已知这个最大数目为X,求相应的n和m。 
*/
#include
#include
#include
#include
#include
using namespace std;
int n,m;
int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        int x;scanf("%d",&x);
        if(x==0){printf("1 1\n");continue;}
        bool bk=false;
        for(int i=1;i*i<=x;i++)
        {
            int j=x/i;
            if(i*j==x && ((i&1)==(j&1)))
            {
                n=(i+j)/2;
                int temp=n-i;
                if(temp==0)continue;
                m=n/temp;
                if(n>=m && (n/m)==temp)
                {
                    printf("%d %d\n",n,m);
                    bk=true;
                    break;
                }
            }
        }
        if(bk==false)printf("-1\n");
    }
    return 0;
}

Codeforces 938D

/*
翻译:
给定一张包含n(n<=2*10^5)个节点的图,给出m(m<=2*10^5)条双向边,边有权,每个点也有权
对于每个点i,你要输出i到任意一个点再回来的最小代价,到达那个点时要加入那个点的点权,经过则不用 
*/
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long LL;
LL d[210000];
struct pt
{
    int x;
    friend bool operator <(pt n1,pt n2){return d[n1.x]>d[n2.x];}
};
priority_queue q;
inline LL read()
{
    LL f=1,x=0;char ch=getchar();
    while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
struct node
{
    LL c;
    int x,y,next;
}a[810000];int len,last[210000];
void ins(int x,int y,LL c)
{
    len++;
    a[len].x=x;a[len].y=y;a[len].c=c;
    a[len].next=last[x];last[x]=len;
}
int n,m,st;
bool v[210000];
int main()
{
    n=read();m=read();st=n+1;
    len=0;memset(last,0,sizeof(last));
    for(int i=1;i<=m;i++)
    {
        int x=read(),y=read();LL c=read();
        ins(x,y,2*c);ins(y,x,2*c);
    }
    for(int i=1;i<=n;i++)
    {
        LL x=read();
        ins(st,i,x);
    }
    memset(d,63,sizeof(d));d[st]=0;
    memset(v,false,sizeof(v));v[st]=true;
    pt tmp;tmp.x=st;q.push(tmp);
    while(!q.empty())
    {
        tmp=q.top();int x=tmp.x;
        for(int k=last[x];k;k=a[k].next)
        {
            int y=a[k].y;
            if(d[y]>d[x]+a[k].c)
            {
                d[y]=d[x]+a[k].c;
                if(v[y]==false)
                {
                    v[y]=true;
                    pt cnt;cnt.x=y;q.push(cnt);
                }
            }
        }
        q.pop();v[x]=false;
    }
    for(int i=1;iprintf("%lld ",d[i]);
    printf("%lld\n",d[n]);
    return 0;
}

Codeforces 939E

/*
翻译:
给出Q(Q<=5*10^5)个操作,共有两种操作
第一种操作输入两个数op x:op表示第几种操作,x表示在当前序列中插入数x(x<=10^9),保证x大于当前序列中任意一个数
第二种操作输入一个数op:op表示第几种操作,求当前序列中的Maximize
定义Maximize为:在当前序列中找出一个子集,Maximize表示子集中数最大值/子集平均数的最大值
输出保留10位小数 
*/
#include
#include
#include
#include
#include
using namespace std;
typedef long long LL;
LL sum[510000],f[510000],list[510000];
int T,head;
int main()
{
    head=0;
    scanf("%d",&T);
    while(T--)
    {
        int op;LL x;
        scanf("%d",&op);
        if(op==1)
        {
            scanf("%I64d",&list[++head]);
            sum[head]=sum[head-1]+list[head];
        }
        else
        {
            int l=1,r=head;
            while(l1)
            {
                int mid=(l+r)/2;
                int mmid=(mid+r)/2;
                if((double)(list[head]+sum[mid])/(mid+1)>(double)(list[head]+sum[mmid])/(mmid+1))l=mid;
                else r=mmid;
            }
            if((double)(list[head]+sum[l])/(l+1)>(double)(list[head]+sum[r])/(r+1))printf("%.10lf\n",(double)list[head]-(double)(list[head]+sum[r])/(r+1));
            else printf("%.10lf\n",(double)list[head]-(double)(list[head]+sum[l])/(l+1));
        }
    }
    return 0;
}

Codeforces 940F

/*
翻译: 
给出一个长度为n(n<=100000)的序列,序列中每个数a[i]<=10^9
设c[i]表示第i种数出现的次数 
q(q<=100000)次询问,询问共有两种
第一种 1 x y 表示求序列中x~y c[i]的mex。mex表示最小的没有出现过的值(不包括0) 
第二种 2 x y 表示把序列中第x位的数替换为y 
*/
#include
#include
#include
#include
#include
#include
using namespace std;
map<int,int> q;
int val[210000],len;
int l,r,t;
struct pck{int p,c,las;}ch[210000];int chlen;
struct ask
{
    int l,r,t,op;
}A[210000];int n,m,alen;
int block,pos[210000];
bool cmp(ask n1,ask n2)
{
    if(pos[n1.l]!=pos[n2.l])return pos[n1.l]<pos[n2.l];
    if(pos[n1.r]!=pos[n2.r])return pos[n1.r]<pos[n2.r];
    return n1.tint vis[210000];//sum[i]的出现次数 
int col[210000],las[210000],answer[210000],ans;//las[i]表示第i个位置上一次的颜色 
int sum[210000];//每种数出现了多少次 
void upd_col(int now,int c)
{
    if(now>=l && now<=r)vis[sum[col[now]]]--,sum[col[now]]--,vis[sum[col[now]]]++;
    col[now]=c;
    if(now>=l && now<=r)vis[sum[col[now]]]--,sum[col[now]]++,vis[sum[col[now]]]++;
}
void del(int now)
{
    vis[sum[col[now]]]--;
    sum[col[now]]--;
    vis[sum[col[now]]]++;
}
void add(int now)
{
    vis[sum[col[now]]]--;
    sum[col[now]]++;
    vis[sum[col[now]]]++;
}
int gtans(){for(int i=1;;i++)if(vis[i]==0)return i;}
int main()
{
    scanf("%d%d",&n,&m);
    block=ceil(pow(n,2.0/3));
    for(int i=1;i<=n;i++)pos[i]=(i-1)/block+1;
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&col[i]);
        val[++len]=col[i];las[i]=col[i];
    }
    for(int i=1;i<=m;i++)
    {
        int op,u,v;
        scanf("%d%d%d",&op,&u,&v);
        if(op==1)
        {
            alen++;
            A[alen].l=u;A[alen].r=v;A[alen].t=chlen;
            A[alen].op=i-chlen;
        }
        else
        {
            chlen++;ch[chlen].p=u;ch[chlen].c=v;
            ch[chlen].las=las[u];las[u]=v;
            val[++len]=v;
        }
    }
    sort(val+1,val+1+len);
    len=unique(val+1,val+1+len)-val-1;
    for(int i=1;i<=len;i++)q[val[i]]=i;
    for(int i=1;i<=chlen;i++)ch[i].las=q[ch[i].las],ch[i].c=q[ch[i].c];
    for(int i=1;i<=n;i++)col[i]=q[col[i]];
    sort(A+1,A+1+alen,cmp);
    l=A[1].l,r=A[1].r,t=A[1].t;
    for(int i=1;i<=A[1].t;i++)col[ch[i].p]=ch[i].c;
    for(int i=A[1].l;i<=A[1].r;i++)
    {
        vis[sum[col[i]]]--;
        sum[col[i]]++;
        vis[sum[col[i]]]++;
    }
    for(int i=1;;i++)if(vis[i]==0){answer[A[1].op]=i;break;}
    for(int i=2;i<=alen;i++)
    {
        while(twhile(t>A[i].t)upd_col(ch[t].p,ch[t].las),t--;
        while(lwhile(l>A[i].l)add(--l);
        while(rwhile(r>A[i].r)del(r--);
        answer[A[i].op]=gtans();
        //for(int j=l;j<=r;j++)printf("%d ",col[j]);
    }
    for(int i=1;i<=alen;i++)printf("%d\n",answer[i]);
    return 0;
}

Codeforces 946D

/*
翻译:
定义一个星期n(n<=500)天,一天m(m<=500)个小时。给定课表,你想翘课,但最多只能翘K(K<=500)节课
定义一天在学校的时间为(该天最后一节课时间-该天第一节课时间+1)
你想要这个星期呆在学校的时间尽量短,求这个最短时间 
*/
#include
#include
#include
#include
#include
using namespace std;
char ch[510][510];
int sum[510][510];//第i天 翘j节课 
int f[510][510];//前i天 翘j节课 
int n,m,K,a[510],s[510],gt[510];
int pre[510];
int main()
{
    scanf("%d%d%d",&n,&m,&K);
    for(int i=1;i<=n;i++)
    {
        int cnt=0;
        scanf("%s",ch[i]+1);
        for(int j=1;j<=m;j++)a[j]=ch[i][j]-'0';
        for(int j=1;j<=m;j++){if(a[j]==1)gt[++cnt]=j,s[i]++;}
        if(cnt!=0)sum[i][0]=m-(gt[cnt]-gt[1]+1);
        else {sum[i][0]=m;continue;}
        for(int j=1;j<=s[i];j++)//翘多少节课 
        {
            if(j==s[i]){sum[i][j]=m;break;}
            int u=s[i]-j;//上多少节课 
            for(int k=1;k<=cnt-u+1;k++)
                sum[i][j]=max(sum[i][j],m-(gt[k+u-1]-gt[k]+1));
        }
    }
    f[0][0]=0;
    for(int i=1;i<=n;i++)
        for(int j=0;j<=K;j++)
            for(int k=0;k<=min(K,s[i]);k++)
            {
                if(j>=k)f[i][j]=max(f[i-1][j-k]+sum[i][k],f[i][j]);
            }
    printf("%d\n",n*m-f[n][K]);
    return 0;
}

Codeforces 946E

/*
翻译:
定义一个数为美丽数,当且仅当这个数长度为偶数,且他的某一个排列可以组成一个回文数
给出n(n<=2*10^100000),求小于n的最大美丽数 
*/
#include
#include
#include
#include
#include
using namespace std;
char ch[210000];
int a[210000],g[15],len;
int f[210000][10];
void sol()
{
    for(int i=len;i>=1;i--)
        for(int j=a[i]-1;j>=0;j--)
        {
            if(i==1 && j==0)break;
            int cnt=0,maxx=0;
            for(int k=0;k<=9;k++)
            {
                int op=0;if(k==j)op=1;
                if(f[i-1][k]^op==1)cnt++,maxx=k;
            }
            if(len-icontinue;
            for(int k=1;k<=i-1;k++)printf("%d",a[k]);
            printf("%d",j);
            for(int k=i+1;k<=len-cnt;k++)printf("9");
            int t=maxx;
            for(int k=len-cnt+1;k<=len;k++)
            {
                int op=0;if(t==j)op=1;else op=0;
                while(f[i-1][t]^op!=1){t--;if(t==j)op=1;else op=0;}
                printf("%d",t);t--;
            }
            printf("\n");
            return ;
        }
    for(int i=1;i2;i++)printf("9");
    printf("\n");
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        memset(g,0,sizeof(g));
        scanf("%s",ch+1);len=strlen(ch+1);
        for(int i=1;i<=len;i++)a[i]=ch[i]-'0',g[a[i]]++;
        if(len%2==1)
        {
            for(int i=1;iprintf("9");
            printf("\n");continue;
        }
        if((g[1]==1 && g[0]==len-1 && a[1]==1) || (g[1]==2 && g[0]==len-2 && a[1]==1 && a[len]==1))
        {
            for(int i=1;i1;i++)printf("9");
            printf("\n");continue;
        }
        for(int i=0;i<=9;i++)f[0][i]=0;//0 偶数次
        for(int i=1;i<=len;i++)
            for(int j=0;j<=9;j++)
            {
                if(a[i]==j)f[i][j]=f[i-1][j]^1;
                else f[i][j]=f[i-1][j];
            }
        sol();
    }
    return 0;
}

Codeforces 946F

/*
翻译: 
定义f[i]=f[i-1]+f[i-2],+表示拼接的意思,即为f[i-1]与f[i-2]拼接起来组成f[i]
给出一个子串(长度<=100),求这个子串在fn(n<=100)的**子序列**中出现了多少次
答案对1e9+7取模
*/
#include
#include
#include
#include
#include
using namespace std;
typedef long long LL;
const LL mod=1e9+7;
LL f[110][110][110];
LL lenth[110];//添加2^lenth[i]次方个数 
char ch[110];int n,m;
int main()
{
    scanf("%d%d",&n,&m);
    scanf("%s",ch+1);
    for(int i=1;i<=n;i++)f[ch[i]-'0'][i][i]=1;
    lenth[0]=lenth[1]=2;
    for(int i=2;i<=m;i++)lenth[i]=(lenth[i-1]*lenth[i-2])%mod;
    for(int i=2;i<=m;i++)
        for(int l=1;l<=n;l++)
            for(int r=l;r<=n;r++)
            {
                LL opx,opy;
                if(l==1)opx=lenth[i-1];else opx=1;
                if(r==n)opy=lenth[i-2];else opy=1;
                f[i][l][r]=(f[i][l][r]+(opx*f[i-2][l][r]+opy*f[i-1][l][r])%mod)%mod;
                for(int k=l;k1][l][k]*f[i-2][k+1][r])%mod;
            }
    printf("%lld\n",f[m][1][n]);
    return 0;
}

Codeforces 946G

/*
翻译:
给出一个长度为n(n<=10^5)的序列,要求最少的次数,使得序列变为一个删去一个数后严格上升的序列 
*/
#include
#include
#include
#include
#include
using namespace std;
int f[2][210000];//没删  删 
int n,pos,ans;
int main()
{
    scanf("%d",&n);
    memset(f,63,sizeof(f));
    f[0][0]=-1e9;
    for(int i=1;i<=n;i++)
    {
        int x;scanf("%d",&x);
        int t=upper_bound(f[1]+1,f[1]+1+n,x-i+1)-f[1];
        f[1][t]=x-i+1;ans=max(ans,t);
        f[1][pos]=min(f[1][pos],f[0][pos]);ans=max(ans,pos);
        t=upper_bound(f[0]+1,f[0]+1+n,x-i)-f[0];
        f[0][pos=t]=x-i;
    }
    printf("%d\n",max(0,n-ans-1));
    return 0;
}

Codeforces 950B

/*
翻译:
给出两个数字串a,b,长度分别为n,m(n,m<=10^6)
求之多能把a,b分成多少部分,使得每一部分分别相等 
*/
#include
#include
#include
#include
#include
using namespace std;
int a[1100000],b[1100000];
int n,m;
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    for(int i=1;i<=m;i++)scanf("%d",&b[i]);
    int i=0,j=0,sx=0,sy=0,ans=0;
    while(i+1<=n && j+1<=m)
    {
        i++;j++;
        sx+=a[i];sy+=b[j];
        while(sx!=sy)
        {
            if(sxelse sy+=b[++j];
        }
        ans++;sx=sy=0;
    }
    printf("%d\n",ans);
    return 0;
}

Codeforces 954A

/*
给定一段长度为n(n<=100)的字符串,R与U可以组合在一起,求组合在一起后最短字符串长度 
*/
#include
#include
#include
#include
#include
using namespace std;
char ch[110];
int main()
{
    int n;
    scanf("%d",&n);
    scanf("%s",ch+1);
    int i=1,cnt=0;
    while(i<=n)
    {
        if((ch[i]=='R' && ch[i+1]=='U') || (ch[i]=='U' && ch[i+1]=='R'))cnt++,i+=2;
        else cnt++,i+=1;
    }
    printf("%d\n",cnt);
    return 0;
}

Codeforces 954B

/*
翻译:
给定一个字符串,每次可以输入1个字符(低端操作)或进行之多一次高端操作
高端操作:复制当前字符串并插入至当前字符串末尾
求可以弄出这个字符串的最小总操作数 
*/
#include
#include
#include
#include
#include
using namespace std;
char ch[110];
int n;
int main()
{
    scanf("%d",&n);
    scanf("%s",ch+1);
    int ans=n;
    for(int i=1;i<=n;i++)
    {
        bool bk=false;
        for(int j=i+1;j<=i+i;j++)if(ch[j]!=ch[j-i]){bk=true;break;}
        if(bk==false)ans=min(ans,n-2*i+1+i);
    }
    printf("%d\n",ans);
    return 0;
}

Codeforces 954C

/*
翻译:
定义一个矩阵u*v由1~u*v组成,位置(i,j)填值(i-1)*v+j。每个格子可以向上下左右走(边界你懂得)
给出一段路线,判断这条路线是否可以在某一个矩阵中走出。不能输出NO,能则输出YES以及某个矩阵的u,v 
*/
#include
#include
#include
#include
#include
using namespace std;
int n;
int a[210000];
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        if(i==1)continue;
        if(a[i]==a[i-1]){printf("NO\n");return 0;}
    }
    if(n==1)
    {
        printf("YES\n1 %d\n",a[1]);
        return 0;
    }
    int x,y,t=1,sx=-1,sy=-1;
    for(int i=2;i<=n;i++)if(abs(a[i]-a[i-1])!=1){sy=abs(a[i]-a[i-1]);break;}
    if(sy==-1)
    {
        int maxx=0;
        for(int i=1;i<=n;i++)maxx=max(maxx,a[i]);
        printf("YES\n1 %d\n",maxx);
        return 0;
    }
    x=(a[1]-1)/sy+1;y=(a[1]-1)%sy+1;
    sx=max(sx,x);
    bool bk=false;
    while(t<=n)
    {
        t++;if(t>n)break;
        if(a[t]==a[t-1]+1)
        {
            if(sy==-1 || yelse{bk=true;break;}
        }
        else if(a[t]==a[t-1]-1)
        {
            if(y==1){bk=true;break;}
            else y--;
        }
        else
        {
            if(a[t]>a[t-1])
            {
                int tmp=a[t]-a[t-1];
                if(sy==-1 || sy==tmp)sy=tmp;
                else {bk=true;break;}
                x++;
            }
            else
            {
                int tmp=a[t-1]-a[t];
                if(sy==-1 || sy==tmp)sy=tmp;
                else {bk=true;break;}
                x--;
                if(x==0){bk=true;break;}
            }
        }
        sx=max(sx,x);
    }
    if(bk==true || (sx>1e9 || sy>1e9))printf("NO\n");
    else printf("YES\n%d %d\n",sx,sy);
    return 0;
}

Codeforces 954D

/*
翻译:
给出一张图,点数n(n<=1000),边数m(m<=1000)。
给出两个点s,t,要在图内新增一条边并保证s->t的最短路径长度不改变
求这样的边有多少条 
*/
#include
#include
#include
#include
#include
using namespace std;
struct node
{
    int x,y,next;
}a[2100];int len,last[1100];
void ins(int x,int y)
{
    len++;
    a[len].x=x;a[len].y=y;
    a[len].next=last[x];last[x]=len;
}
int n,m,stx,sty;
bool v[1100];
int d[2][1100],list[1100],head,tail,st;
void spfa(int op)
{
    memset(v,false,sizeof(v));v[st]=true;
    memset(d[op],63,sizeof(d[op]));d[op][st]=0;
    list[1]=st;head=1;tail=2;
    while(head!=tail)
    {
        int x=list[head];
        for(int k=last[x];k;k=a[k].next)
        {
            int y=a[k].y;
            if(d[op][y]>d[op][x]+1)
            {
                d[op][y]=d[op][x]+1;
                if(v[y]==false)
                {
                    v[y]=true;
                    list[tail++]=y;
                    if(tail==n+1)tail=1;
                }
            }
        }
        head++;if(head==n+1)head=1;
        v[x]=false;
    }
}
bool mp[1100][1100];
int main()
{
    scanf("%d%d%d%d",&n,&m,&stx,&sty);
    memset(mp,false,sizeof(mp));len=0;memset(last,0,sizeof(last));
    for(int i=1;i<=m;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);mp[x][y]=mp[y][x]=true;
        ins(x,y);ins(y,x);
    }
    st=stx;spfa(0);
    st=sty;spfa(1);
    int ans=0;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)if(i!=j && mp[i][j]==false)
        {
            mp[i][j]=mp[j][i]=true;
            if(d[0][i]+d[1][j]+1>=d[0][sty] && d[0][j]+d[1][i]+1>=d[0][sty])ans++;
        }
    printf("%d\n",ans);
    return 0;
}

Codeforces 954E

/*
翻译:
给定n(n<=2*10^5)个水龙头,第i个水龙头有最大出水量a[i](a[i]<=10^6),且给定一个温度值t[i](t[i]<=10^6)。
定义一次出水得到的温度为Sigma(a[i]*t[i])/Sigama(a[i]),给定一次出水得到的温度,求最大总出水量。
如果得不到该温度,输出0 
*/
#include
#include
#include
#include
#include
using namespace std;
typedef long long LL;
int n,T;
struct node
{
    LL a,t;
}P[1110000];
bool cmp(node n1,node n2){return n1.tint main()
{
    scanf("%d%d",&n,&T);
    for(int i=1;i<=n;i++)scanf("%lld",&P[i].a);
    for(int i=1;i<=n;i++)scanf("%lld",&P[i].t);
    LL sx=0,sy=0,ax=0,ay=0;
    for(int i=1;i<=n;i++)
    {
        if(P[i].t>T)sx+=P[i].a*(P[i].t-T),ax+=P[i].a;
        else if(P[i].tdouble ans=0;LL sum=0;
    if(sx//负的多 
    {
        ans=(double)ax;sum=sx;
        sort(P+1,P+1+n,cmp);
        int tmp=n;
        for(int i=1;i<=n;i++)if(P[i].t>=T){tmp=i-1;break;}
        for(int i=tmp;i>=1;i--)
        {
            if(sum-P[i].a*(T-P[i].t)>0)sum-=P[i].a*(T-P[i].t),ans+=(double)P[i].a;
            else
            {
                ans+=(double)sum/(T-P[i].t);
                sum=0;
                break;
            }
        }
        for(int i=1;i<=n;i++)if(P[i].t==T)ans+=(double)P[i].a;
        if(sum==0)printf("%.15lf\n",ans);
        else printf("0\n");
    }
    else
    {
        ans=(double)ay;sum=sy;
        sort(P+1,P+1+n,cmp);
        int tmp=1;
        for(int i=n;i>=1;i--)if(P[i].t<=T){tmp=i+1;break;}
        for(int i=tmp;i<=n;i++)
        {
            if(sum-P[i].a*(P[i].t-T)>0)sum-=P[i].a*(P[i].t-T),ans+=(double)P[i].a;
            else
            {
                ans+=(double)sum/(P[i].t-T);
                sum=0;
                break;
            }
        }
        for(int i=1;i<=n;i++)if(P[i].t==T)ans+=(double)P[i].a;
        if(sum==0)printf("%.15lf\n",ans);
        else printf("0\n");
    }
    return 0;
}

Codeforces 954F

/*
翻译:
给定一个3行m(m<=10^18)列的矩阵,从格子(i,j)可以移到(i,j+1)与(i-1(i>1),j+1),(i+1(i<3),j+1)
矩阵内会存在n个位于a[i]行,坐标l[i]~r[i]的障碍物,障碍物不能通行
求从格子(2,1)移动至(2,m)的方案数,答案对1e9+7取模 
*/
#include
#include
#include
#include
#include
using namespace std;
typedef long long LL;
const LL mod=1e9+7;
struct node
{
    LL l,r;int a;
}P[11000];
LL s[21000];
int t,c[5][41000],pre[5];
int n;LL m;
struct matrix
{
    LL m[5][5];
    matrix(){memset(m,0,sizeof(m));}
    void cr(){m[1][1]=m[1][2]=m[2][1]=m[2][2]=m[2][3]=m[3][2]=m[3][3]=1;m[1][3]=m[3][1]=0;}
}tmp;
matrix mul(matrix u,matrix v,int n,int m,int p)
{
    matrix ret;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            for(int k=1;k<=p;k++)
                ret.m[i][k]=(ret.m[i][k]+u.m[i][j]*v.m[j][k])%mod;
    return ret;
}
matrix pow_mod(matrix u,LL b)
{
    matrix ans;
    if(b==0)return u;
    for(int i=1;i<=3;i++)ans.m[i][i]=1;
    while(b)
    {
        if(b%2==1)ans=mul(ans,u,3,3,3);
        u=mul(u,u,3,3,3);b/=2;
    }
    return ans;
}
int main()
{
    t=0;
    scanf("%d%lld",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%d%lld%lld",&P[i].a,&P[i].l,&P[i].r);
        s[++t]=P[i].l-1;s[++t]=P[i].r;
    }
    s[++t]=1;s[++t]=m;
    sort(s+1,s+1+t);
    t=unique(s+1,s+1+t)-s-1;
    memset(c,0,sizeof(c));
    for(int i=1;i<=n;i++)
    {
        int l=lower_bound(s+1,s+1+t,P[i].l-1)-s;
        int r=lower_bound(s+1,s+1+t,P[i].r)-s;
        c[P[i].a][l]++;c[P[i].a][r]--;
    }
    matrix ans;
    ans.m[1][1]=ans.m[1][3]=0;ans.m[1][2]=1;
    memset(pre,0,sizeof(pre));
    for(int u=1;ufor(int j=1;j<=3;j++)
        {
            pre[j]+=c[j][u];
            if(pre[j])tmp.m[1][j]=tmp.m[2][j]=tmp.m[3][j]=0;
        }
        tmp=pow_mod(tmp,s[u+1]-s[u]);
        ans=mul(ans,tmp,1,3,3);
    }
    printf("%lld\n",ans.m[1][2]);
    return 0;
}

Codeforces 954G

/*
翻译:
给出一个长度为n的序列,给出值r,k,定义一个sum[i]表示i-r~i+r的和,共有值为k的数可以加入序列中的数里,求min(sum[i])的最大值
如给出长度为5的序列5 4 3 4 9,给定r=0,k=6
那么序列可以变为6 6 5 5 9,得出最优解min(sum[i])=5 
1<=r<=n<=500000,k<=10^18
*/
#include
#include
#include
#include
#include
using namespace std;
typedef long long LL;
LL k,a[510000],b[510000];
int n,r;
bool chk(LL p)
{
    LL cnt=k,sum=0;
    for(int i=1;i<=n;i++)b[i]=a[i];
    for(int i=1;i<=1+r;i++)sum+=b[i];
    int i=1;
    while(i<=n)
    {
        if(sumif(u>cnt)return false;
            b[min(n,i+r)]+=u;cnt-=u;sum=p;
        }
        if(i-r>=1)sum-=b[i-r];
        if(i+1+r<=n)sum+=b[i+1+r];
        i++;
    }
    return true;
}
int main()
{
    scanf("%d%d%I64d",&n,&r,&k);
    for(int i=1;i<=n;i++)scanf("%I64d",&a[i]);
    LL l=0,r=(1LL<<63-1LL),ans;
    while(l<=r)
    {
        LL mid=(l+r)/2;
        if(chk(mid))ans=mid,l=mid+1;
        else r=mid-1;
    }
    printf("%I64d\n",ans);
    return 0;
}

Codeforces 955A

/*
翻译:
给猫喂食,初始饥饿值为H,每分钟增加饥饿值D。商店中每块面包售价cost,补充饥饿值N点。当时间大于等于20:00时售价打八折,求问能把猫喂饱的最少价格 
*/
#include
#include
#include
#include
#include
using namespace std;
int hh,mm;
int H,D,N;
double cost;
int main()
{
    scanf("%d%d",&hh,&mm);
    scanf("%d%d%lf%d",&H,&D,&cost,&N);
    double cx,cy;
    double T;
    if(H%N==0)T=(H/N);
    else T=(H/N)+1;
    if(hh<20)cx=cost*T;
    else cx=cost*0.8*T;
    int u=(60*(20-hh-1)+60-mm)*D+H;
    if(u%N==0)T=(u/N);
    else T=(u/N)+1;
    if(hh<20)cy=cost*0.8*T;
    printf("%.4lf\n",min(cx,cy));
    return 0;
}

Codeforces 955B

/*
翻译: 
给出一个串,要求判断这个串能否被拆分成两个部分,这两个部分可以被分成两种不同字母组成的串
*/
#include
#include
#include
#include
#include
using namespace std;
int tmp[110000],u[110000];
char ch[110000];
bool cmp(int n1,int n2){return n1>n2;}
int main()
{
    scanf("%s",ch+1);int len=strlen(ch+1);
    if(len<4){printf("No\n");return 0;}
    for(int i=1;i<=len;i++)tmp[i]=ch[i]-'a'+1;
    sort(tmp+1,tmp+1+len);
    int T=0;
    for(int i=2;i<=len;i++)if(tmp[i]!=tmp[i-1])T++;
    if(T>3 || T==0){printf("No\n");return 0;}
    if(T==3 || T==2){printf("Yes\n");return 0;}
    //不同字符共 2个 
    int maxx=0;
    for(int i=1;i<=len;i++)u[tmp[i]]++,maxx=max(maxx,tmp[i]);
    sort(u+1,u+1+maxx,cmp);
    if(u[1]==1 || u[2]==1)printf("No\n");
    else printf("Yes\n");
    return 0;
}

Codeforces 957A

/*
翻译:
给出一个可能未填满的串以及三种字符,相邻的两位不能填同样的字符,要求能否求出至少两种方案使得满足以上要求 
*/
#include
#include
#include
#include
#include
using namespace std;
char ch[110];
int main()
{
    int n;
    scanf("%d",&n);
    scanf("%s",ch+1);
    bool bk=true;bool bkk=false;
    for(int i=1;iif(ch[i]==ch[i+1] && ch[i]!='?'){bk=false;break;}
    if(bk==false){printf("No\n");return 0;}
    for(int i=1;i<=n;i++)if(ch[i]=='?')bkk=true;
    if(bkk==false){printf("No\n");return 0;}
    for(int i=1;iif(ch[i]==ch[i+1] && ch[i]=='?'){bk=false;break;}
    if(bk==false){printf("Yes\n");return 0;}
    for(int i=1;i<=n;i++)if(ch[i]=='?' && (ch[i-1]==ch[i+1] || i==1 || i==n)){bk=false;break;}
    if(bk==false)printf("Yes\n");
    else printf("No\n");
    return 0;
}

你可能感兴趣的:(Codeforces)