【长期计划】Atcoder题目泛做

之前学长跟我说的是700-的应该都能自己做? 然后1000-的应该都能有一定的思路?

记不清了 但总之是要智力康复一下 又加上文化课比较紧 所以这个大概就会是长期计划了

————————————分鸽线————————————

今天体育中考晚上没事颓了3道题。

AGC024【至于为什么是24呢因为今天是24号233】

三道巨水的题我竟然A题WA了三发BC都1A...

A
B
C

————————————分鸽线————————————

竟然没让我们继续上课。本来以为体育中考和周六的课直接对调了的。

AGC025

A太水了不写了

B直接组合没有任何技术含量。。睿智的我RE了好几发。

//Love and Freedom.
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#define ll long long
#define inf 20021225
#define mdn 998244353
#define N 900010 
using namespace std;

int a,b,n; ll k;
int fac[N],inv[N];
int ksm(int bs,int mi)
{
    int ans=1;
    while(mi)
    {
        if(mi&1)
            ans=(ll)ans*bs%mdn;
        bs=(ll)bs*bs%mdn; mi>>=1;
    }
    return ans;
}
int C(int n,int m)
{
    if(n<m)    return 0;
    return (ll)fac[n]*inv[m]%mdn*inv[n-m]%mdn;
}
void upd(int &x,int y){x=(x+y)%mdn;} 
int main()
{
    int ans=0;
    scanf("%d%d%d%lld",&n,&a,&b,&k);
    fac[0]=inv[0]=1;
    for(int i=1;i<=n;i++)    fac[i]=(ll)fac[i-1]*i%mdn;
    inv[n]=ksm(fac[n],mdn-2);// printf("%d
",inv[n]);
    for(int i=n-1;i;i--)    inv[i]=(ll)inv[i+1]*(i+1)%mdn;
    for(int i=0;i<=n&&(ll)i*a<=k;i++)
    {
        if((k-a*i)%b==0)
        {
            ll bi=(k-a*i)/b;
            upd(ans,(ll)C(n,i)*C(n,bi)%mdn);
        }
    }
    printf("%d
",ans);
    return 0;
}
/**
300000 300000 300000 0
*/
B

C题就贪个心然后写起来巨烦不写了QAQ

滚去学文化了嘤嘤嘤

 额。。晚上打了个ABC125怎么这么简单啊。。。AK了怎么才258名好菜啊。。。

还是把代码丢下吧。。。

//Love and Freedom.
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#define ll long long
#define inf 20021225
using namespace std;

int main()
{
    int a,b,t;
    scanf("%d%d%d",&a,&b,&t);
    printf("%d
",(t/a)*b);
    return 0;
}
A
//Love and Freedom.
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#define ll long long
#define inf 20021225
using namespace std;
int c[21],v[21];
int main()
{
    int st,top,n;
    scanf("%d",&n); top=1<<n;
    for(int i=0;i<n;i++)    scanf("%d",&v[i]);
    for(int i=0;i<n;i++)    scanf("%d",&c[i]);
    int ans=0;
    for(int st=1;st<top;st++)
    {
        int tmpv=0,tmpc=0;
        for(int i=0;i<n;i++)    if((st>>i)&1)
            tmpv+=v[i],tmpc+=c[i];
        ans=max(ans,tmpv-tmpc);
    }
    printf("%d
",ans);
    
    return 0;
}
B
//Love and Freedom.
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<map>
#define ll long long
#define inf 20021225
#define N 100010
using namespace std;

int a[N]; int n; int pre[N],suf[N];
int gcd(int x,int y){return !y?x:gcd(y,x%y);}
void solve()
{
    for(int i=1;i<=n;i++)
    {
        if(i==1)    pre[i]=a[i];
        else    pre[i]=gcd(pre[i-1],a[i]);
    }
    
    for(int i=n;i;i--)
    {
        if(i==n)    suf[i]=a[i];
        else    suf[i]=gcd(suf[i+1],a[i]);
    }
    int ans=1;
    for(int i=1;i<=n;i++)
    {
        if(i==1)    ans=max(ans,suf[2]);
        else if(i==n)    ans=max(ans,pre[n-1]);
        else    ans=max(ans,gcd(pre[i-1],suf[i+1]));
    }
    printf("%d
",ans);
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    solve();
    return 0;
}
C
//Love and Freedom.
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#define ll long long
#define inf 20021225
#define N 100010 
using namespace std;
ll f[N][2]; ll a[N]; int n;
void solve()
{
    memset(f,-48,sizeof(f)); f[0][0]=f[0][1]=0;
    for(int i=1;i<=n;i++)
    {
        if(i==1)    f[i][0]=a[i];
        else
        {
            f[i][0]=max(f[i-1][0],f[i-1][1])+a[i];// printf("QAQ %d %lld
",i,a[i]);
            f[i][1]=max(f[i-1][0]-2*a[i-1],f[i-1][1]+2*a[i-1])-a[i];
        }
    }
    printf("%lld
",max(f[n][0],f[n][1]));
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%lld",&a[i]);
    solve(); 
    return 0;
}
D

 ————————————分鸽线————————————

AGC026

B是个特判 就是看一下(kd+a)%b>c是否存在就行了

C是个典型的meet in the middle 模数要设的大一点不然会冲突 我直接unsigned long long了 不卡好评

//Love and Freedom.
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#define ll long long
#define inf 20021225
using namespace std;
ll a,b,c,d;
ll gcd(ll x,ll y){return y?gcd(y,x%y):x;}
bool okay(ll a,ll b,ll c,ll d)
{
    ll g=gcd(d,b); ll x=(b-a)/g*g;
    if((x+a)%b>c)    return 0;
    x=(b-a-1)/g*g;
    if((x+a)%b>c)    return 0;
    return 1; 
}
int main()
{
    int t; scanf("%d",&t);
    while(t--)
    {
        scanf("%lld%lld%lld%lld",&a,&b,&c,&d);
        if(a<b || b>d){printf("No
"); continue;}    a%=b;
        if(okay(a,b,c,d))    printf("Yes
");
        else    printf("No
");
    }
    return 0;
}
B
//Love and Freedom.
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<map>
#define ll long long
#define inf 20021225
#define bs 331
#define ull unsigned long long
using namespace std;
map<ull,int> f[20]; char ch[40]; int col[20],n; ll ans;
ull pw[20];
void calc(int fl)
{
    ull x=0,y=0;
    int p=0,q=n;
    for (int i=1;i<=n;i++)
        if(col[i]>0) x+=(ull)col[i]*pw[p],p++;
        else y+=(ull)col[i]*pw[q],q--;
    if(fl)    ans+=f[p][x+y];
    else    f[q][x+y]++;
}
void dfs1(int x)
{
    if(x>n){calc(0); return;}
    col[x]=ch[x]-'a'+1; dfs1(x+1); col[x]=-col[x]; dfs1(x+1);
}
void dfs2(int x)
{
    if(x<=n){calc(1); return;}
    col[2*n-x+1]=ch[x]-'a'+1; dfs2(x-1); col[2*n-x+1]=-col[2*n-x+1]; dfs2(x-1);
}
int main()
{
    scanf("%d",&n); scanf("%s",ch+1); pw[0]=1; for(int i=1;i<=n;i++) pw[i]=pw[i-1]*bs;
    dfs1(1); dfs2(2*n); printf("%lld
",ans);
    return 0;
}
C

 ————————————分鸽线————————————

AGC034

A特判 B在整 感冒真不舒服

//Love and Freedom.
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#define ll long long
#define inf 20021225
using namespace std;
char ch[200001]; int a,b,c,d,n;
int main()
{
    scanf("%d%d%d%d%d",&n,&a,&b,&c,&d);
    int f=(d<c); scanf("%s",ch+1);
    for(int i=b-1;i<=d-1;i++)
    {
        if(i+2>n)    continue;
        if(ch[i]=='.'&&ch[i+1]=='.'&&ch[i+2]=='.')
            f=0;
    }
    for(int i=a;i<=max(c,d)-1;i++)
        if(ch[i]=='#'&&ch[i+1]=='#'){f=1;break;}
    if(f==1)    printf("No
");
    else    printf("Yes
");
    return 0;
}
A

 ————————————分鸽线————————————

AGC028

B有点意思

就是考虑每个x的贡献 对于i~x只要都没拿的话就有贡献 那么可以推出柿子

sum_{i=1}^x(n-x+i-1)!*(x-i)!*C(n,x-i+1)

这里写的是i在x之前 不然加abs懒得写了

意思大概是除了i~x的全排 然后i必须是i~x里最先拿走的所以剩下的可以随便排 再就是要选出一些位置来放i~x

观察到x-i一直都在 简化一下

sum_{k=0}^{x-1}(n-k-1)!*k!*C(n,k+1)

这个显然可以预处理 然后后半部分(x+1~n)是一样的

然后就做完啦

还发现了一种非常神仙的做法 先把这个题转成期望... 然后再*n!

看起来有点闲 但是非常好想好做的说 orz forever_shi 链接:戳我

————————————分鸽线————————————

AGC030D

找sun要到了一道好题 也是计数转期望

这个题当时做了 没做出来(

膜了一下题解 很有趣的问题呢

我们用f[i][x][y]来表示第i轮操作后ax>ay的概率 由于逆序对贡献是1 最后全部加起来就是期望

每次交换的概率是1/2 然后我们最后把整体*2^q就可以了

还看了一道sun的类似的题 link挂这里了:戳我

大体总结一下这类题的方法:

1.首先要对期望的贡献一样才能通过期望求概率 这个应该很显然能看出来

2.一般是关于全排列或者2^n的问题 来用期望来做

好像atcoder非常喜欢出这种东西...

代码扔这里了

//Love and Freedom.
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#define ll long long
#define inf 20021225
#define N 3001
#define mdn 1000000007
#define inv 500000004ll 
using namespace std;

int f[N][N],a[N],n,q;
int ksm(int bs,int mi)
{
    int ans=1;
    while(mi)
    {
        if(mi&1)    ans=1ll*ans*bs%mdn;
        bs=1ll*bs*bs%mdn; mi>>=1;// printf("QAQ");
    }
    return ans;
}
int main()
{
    scanf("%d%d",&n,&q); int remq=q;
    for(int i=1;i<=n;i++)    scanf("%d",&a[i]);
    for(int i=1;i<=n;i++)    for(int j=1;j<=n;j++)
        f[i][j]=a[i]>a[j];
    while(q--)
    {
        int x,y; scanf("%d%d",&x,&y);
        f[x][y]=f[y][x]=inv*(f[x][y]+f[y][x])%mdn;
        for(int i=1;i<=n;i++)    if(i!=x&&i!=y)
            f[x][i]=f[y][i]=inv*(f[x][i]+f[y][i])%mdn,
            f[i][x]=f[i][y]=inv*(f[i][x]+f[i][y])%mdn;
    }
    int ans=0; 
    for(int i=1;i<=n;i++)    for(int j=1;j<i;j++)
        ans=(ans+f[j][i])%mdn;
    printf("%d
",1ll*ans*ksm(2,remq)%mdn);
    return 0;
}
D

发现自己概率期望真的不大行... 所以接下来要开始练一练...

————————————分鸽线————————————

突然发现ABC131没有往上搬... 把EF搬上来吧

E问的是构造简单连通图 n个点 k对点对最短距离是2

萧昈黎tql orz

我们先造个菊花 然后接下来每加1条边就少一对点对 就做完了

//Love and Freedom.
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#define ll long long
#define inf 20021225
using namespace std;
bool edg[101][101]; int n,k,m;
int main()
{
    scanf("%d%d",&n,&k); m=n*(n-1)/2;
    m-=k;
    if(m<n-1)
    {
        printf("-1"); return 0;
    }
    printf("%d
",m); m-=n-1; for(int i=2;i<=n;i++)    edg[i][1]=1;
    for(int i=2;i<=n&&m;i++)    for(int j=i+1;j<=n&&m;j++)
        edg[i][j]=1,m--;
    for(int i=1;i<=n;i++)    for(int j=1;j<=n;j++)
        if(edg[i][j])    printf("%d %d
",i,j);
    return 0;
}
E

F是平面上n个点 如果有三个点分别位于(a,b) (a,d) (c,b)就可以添加一个新点(c,d) 问最多能操作多少次

显然新点不会产生贡献

我们可以维护联通块 对行列分别建点 然后一个点坐标是(x,y)的话就连接第x行和第y列 于是我们就可以通过维护联通块来求答案

ans=行数*列数-点数(点数是平面里的点数)

//Love and Freedom.
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#define ll long long
#define inf 20021225
#define N 100010
using namespace std;

int fa[N<<1],val[N<<1][2],n;
int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
struct poi{int x,y,ax,ay;}a[N];
bool cmp1(poi x,poi y){return x.x<y.x;}
bool cmp2(poi x,poi y){return x.y<y.y;}
void merge(int x,int y)
{
    int fx=find(x),fy=find(y); if(fx==fy)    return;
    val[fx][0]+=val[fy][0]; val[fx][1]+=val[fy][1];
    fa[fy]=fx; 
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d%d",&a[i].x,&a[i].y);
    int xx=0,yy=0;
    sort(a+1,a+n+1,cmp1);
    for(int i=1;i<=n;i++)
    {
        if(a[i].x!=a[i-1].x)    ++xx;
        a[i].ax=xx; 
    }
    sort(a+1,a+n+1,cmp2);
    for(int i=1;i<=n;i++)
    {
        if(a[i].y!=a[i-1].y)    ++yy;
        a[i].ay=yy;
    }
    for(int i=1;i<=xx;i++)    fa[i]=i,val[i][0]=1;
    for(int i=1;i<=yy;i++)    fa[i+xx]=i+xx,val[i+xx][1]=1;
    for(int i=1;i<=n;i++)    merge(a[i].ax,a[i].ay+xx);
    ll ans=0;
    for(int i=1;i<=xx+yy;i++)
        if(fa[i]==i)    ans+=1ll*val[i][0]*val[i][1];
    printf("%lld
",ans-n);
    return 0;
}
F

他们都好神仙 我好菜(

——————————分鸽线——————————

AGC036

口胡一时爽 一直口胡一直爽

我来先口胡一个A和B

A的做法好像很多 我的想法是一个矩形减去3个三角形 然后这个东西在sqrtn附近构造一下就应该可以了

sun给出的做法比较科学 我们可以考虑两个向量 最后的答案是1/2*(AC-BD) 我们强制B=1然后构造比较方便(诶其实好像和我那个差不多啊(?

处理一下就行了

B的做法我也口胡一个 就是我们可以发现每次最后会剩下一段然后再加进来又会把上次剩余的删掉 这个循环节显然是不超过N的 所以我们可以暴力找到循环节然后剩下的部分也不超过N 也暴力模拟就可以了

C的题解已经写了 sun好神仙啊 %sun

————————分割线————————

AGC007

————————分割线————————

arc094f

连猜两个结论= =

先是n<=3爆搜得到答案= =

n>=4 方案数是和%3与原串相等且存在相邻的是一样的(归纳可证)。

有一些细节懒得说了。

//Love and Freedom.
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#include<string>
#define ll long long
#define inf 20021225
#define N 200010
#define mdn 998244353 
using namespace std;
int read()
{
    int s=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();}
    while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
    return f*s;
}
int f[N][3][3][2],n,ans; char ch[N]; string gg; map<string,bool> vis;
void upd(int &x,int y){x+=x+y>=mdn?y-mdn:y;}
void dfs(string a)
{
    if(vis[a])    return;
    string qwq=a; ans++; vis[a]=1;
    for(int i=0;i<n-1;i++)    if(qwq[i]!=qwq[i+1])
    {
        if((qwq[i]=='a' && qwq[i+1]=='b')||(qwq[i]=='b'&&qwq[i+1]=='a'))
            a[i]=a[i+1]='c',dfs(a),a[i]=qwq[i],a[i+1]=qwq[i+1];
        if((qwq[i]=='a' && qwq[i+1]=='c')||(qwq[i]=='c'&&qwq[i+1]=='a'))
            a[i]=a[i+1]='b',dfs(a),a[i]=qwq[i],a[i+1]=qwq[i+1]; 
        if((qwq[i]=='b' && qwq[i+1]=='c')||(qwq[i]=='c'&&qwq[i+1]=='b'))
            a[i]=a[i+1]='a',dfs(a),a[i]=qwq[i],a[i+1]=qwq[i+1]; 
    }
}
int main()
{
    scanf("%s",ch+1); n=strlen(ch+1);
    if(n<=3)
    {
        for(int i=1;i<=n;i++)    gg=gg+ch[i];
        dfs(gg),printf("%d
",ans); return 0;
    }
    int flag=0,fs=ch[1]-'a';
    for(int i=2;i<=n;i++)    flag+=(ch[i]==ch[i-1]),(fs+=ch[i]-'a')%=3;
    if(flag==n-1)    return puts("1"),0;
    f[1][0][0][0]=1; f[1][1][1][0]=1; f[1][2][2][0]=1;
    for(int i=2;i<=n;i++)
    {
        for(int j=0;j<3;j++)    for(int k=0;k<3;k++)
            for(int s=0;s<3;s++)    for(int p=0;p<2;p++)
            {
                int np=(j==k)|p,ns=(k+s)%3;
                upd(f[i][k][ns][np],f[i-1][j][s][p]); 
            }
    }
    int ans=((ll)f[n][0][fs][1]+f[n][1][fs][1]+f[n][2][fs][1]+(!flag))%mdn;
    printf("%d
",ans);
    return 0;
}
ARC094F
原文地址:https://www.cnblogs.com/hanyuweining/p/10764581.html