Comet OJ - Contest #13

第一次打这种比赛。还是有不少问题的,以后改吧。
A题WA了两次罚了不少时。
C写到一半发现只能过1,就先弃了。
D一眼没看出来。第二眼看出来就是一个类似于复数的快速幂。
然后B切了。
最后切C,图中还重构了一次。还TLE了3发。浪费了大量时间。
Tips:
1、A题FB基本上拿不到的,好好写1A就没事了。
2、先看一遍,大码题和数据结构放后面。
3、先开数论,就TM死刚数论。(这次要是切A之后直接刚D就有FB了)
4、别急,奖励拿不拿就那样吧。
下面是solution:

A

签到题。

#include<bits/stdc++.h>
using namespace std;
namespace IO
{
    char ibuf[(1<<21)+1],obuf[(1<<21)+1],st[15],*iS,*iT,*oS=obuf,*oT=obuf+(1<<21);
    char Get(){return (iS==iT? (iT=(iS=ibuf)+fread(ibuf,1,(1<<21)+1,stdin),(iS==iT? EOF:*iS++)):*iS++);}
    void Flush(){fwrite(obuf,1,oS-obuf,stdout),oS=obuf;}
    void Put(char x){*oS++=x;if(oS==oT)Flush();}
    int read(){int x=0,c=Get();while(!isdigit(c))c=Get();while(isdigit(c))x=x*10+c-48,c=Get();return x;}
    void write(int x){int top=0;if(!x)Put('0');while(x)st[++top]=(x%10)+48,x/=10;while(top)Put(st[top--]);Put(' ');}
    char fetch(){char ch=Get();while(ch^'B'&&ch^'G')ch=getchar();return ch;}
}
using namespace IO;
int main()
{
    int i,n=read();int b=0;
    for(i=1;i<=n;++i) if(fetch()=='G') ++b;
    cout<<b;
}

B

模拟题。

#include<bits/stdc++.h>
#define pi pair<int,int>
#define pub push_back
#define puf push_front
#define pob pop_back
#define fi first
#define se second
using namespace std;
const int N=401;
char str[N],opt[100001];int a[N][N],n,m;deque<pi>q;map<char,int>mp;
int dx[5]={0,-1,0,1,0},dy[5]={0,0,-1,0,1};
int in(int x,int y){return x>=1&&x<=n&&y>=1&&y<=m;}
int main()
{
    int i,j,op,nx,ny;
    mp['W']=1,mp['A']=2,mp['S']=3,mp['D']=4;
    cin>>n>>m;
    for(i=1;i<=n;++i)
    {
    scanf("%s",str+1);
    for(j=1;j<=m;++j)
        if(str[j]=='o') a[i][j]=1;
        else if(str[j]=='@') q.pub(pi(i,j)),nx=i,ny=j;
    }
    scanf("%s",opt+1);
    for(i=1;i<=strlen(opt+1);++i)
    {
    op=mp[opt[i]],nx+=dx[op],ny+=dy[op];
    if(!in(nx,ny)) {puts("GG");return 0;}
    q.puf(pi(nx,ny));
    if(a[nx][ny]) a[nx][ny]=0; else q.pob();
    }
    for(auto x:q) a[x.fi][x.se]=2;
    a[q.front().fi][q.front().se]=3;
    for(i=1;i<=n;++i)
    {
    for(j=1;j<=m;++j)
    {
        if(a[i][j]==1) putchar('o');
        else if(a[i][j]==2) putchar('X');
        else if(a[i][j]==3) putchar('@');
        else putchar('.');
    }
    puts("");
    }
}

C

全图开个并查集维护连通块。
每一行开个并查集维护下一个\(0\)的位置。
实时维护答案。
每次把每一行的没覆盖的\(0\)变成\(1\),并把其与四角中存在的\(1\)合并。
易证其正确性。

#include<iostream>
#include<cstdio>
using namespace std;
const int N=1001;
int n,m,ans,fa[N*N],size[N*N],f[N][N],vis[N*N],mp[N][N];char str[N];
int h(int x,int y){return (x-1)*m+y;}
int Find(int x){return x==fa[x]? x:fa[x]=Find(fa[x]);}
int fd(int s,int x){return x==f[s][x]? x:f[s][x]=fd(s,f[s][x]);}
int read(){int x;scanf("%d",&x);return x;}
void merge(int a,int b)
{
    if(size[a]>size[b]) fa[b]=a,size[a]+=size[b];
    else fa[a]=b,size[b]+=size[a];
}
int main()
{
    scanf("%d%d",&n,&m);int i,j,Q,x1,y1,x2,y2,a,b;
    for(i=1;i<=n;++i)
    {
    scanf("%s",str+1);
    for(j=1;j<=m;++j) mp[i][j]=str[j]=='1';
    }
    for(i=1;i<=n;++i)
        for(j=1;j<=m;++j)
    {
        fa[h(i,j)]=h(i,j),size[h(i,j)]=1;
        if(mp[i][j])
        {
        ++ans,a=h(i,j);
        if(i^1&&mp[i-1][j]) --ans,merge(Find(h(i-1,j)),a);
        a=Find(a);
        if(j^1&&mp[i][j-1]&&a^(b=Find(h(i,j-1)))) --ans,merge(a,b);
        }
    }
    for(i=1;i<=n;++i) for(j=1;j<=m;++j) f[i][j]=j;
    for(i=1;i<=n;++i) for(j=1;j<m;++j) if(mp[i][j+1]) f[i][j]=j+1;
    for(Q=read();Q;--Q)
    {
    x1=read(),y1=read(),x2=read(),y2=read();
    for(i=x1;i<=x2;++i)
    {
        for(j=y1;j<=y2;j=fd(i,j)+1)
        if(!mp[i][j])
        {
            mp[i][j]=1,++ans,a=h(i,j);
            if(i^1&&mp[i-1][j]&&a^(b=Find(h(i-1,j)))) --ans,merge(a,b);
            a=Find(a);
            if(j^1&&mp[i][j-1]&&a^(b=Find(h(i,j-1)))) --ans,merge(a,b);
            a=Find(a);
            if(i^n&&mp[i+1][j]&&a^(b=Find(h(i+1,j)))) --ans,merge(a,b);
            a=Find(a);
            if(j^m&&mp[i][j+1]&&a^(b=Find(h(i,j+1)))) --ans,merge(a,b);
        }
        f[i][y1]=fd(i,y2);
    }
    cout<<ans<<endl;
    }
}

D

题解似乎用的是二次剩余+矩阵快速幂...
实际上我们可以这样理解:
我们要求的是\(\sum\limits_{i=0}^{\lfloor\frac n2\rfloor}\sqrt a^{2i}b^{n-2i}{n\choose 2i}\)。
这个东西很像二项式定理对吧。
实际上就是\((\sqrt a+b)^n=\sum\limits_{i=0}^n\sqrt a^ib^{n-i}{n\choose i}\)中\(\sqrt a\)的指数为偶数的项的和。
这样就好做了。
类似于虚数单位\(i\)一样,我们将\(\sqrt a\)记做一个新的单位,这个单位的平方\(\sqrt a^2=a\)(不管其有没有二次剩余都可以这么认为)。那么所有的数都可以记做\(x*\sqrt a+y*1\),乘法加法直接搬复数的那一套就行了。
那么我们考虑在\((\sqrt a+b)^n\)的展开式中,\(\sqrt a\)的指数为偶数的项一定是\(x*1\)的形式,\(\sqrt a\)的指数为奇数的项一定是\(x*\sqrt a\)的形式。
也就是说,我们要求的\((\sqrt a+b)^n\)的展开式中\(\sqrt a\)的指数为偶数的项的和就是\((\sqrt a+b)^n\)的结果中\(1\)前面的系数。
直接快速幂做即可。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll n,a,b,p;
ll mul(ll a,ll b){return (__int128)a*b%p;}
ll inc(ll a,ll b){a+=b;return a>=p? a-p:a;}
struct node{ll x,y;node(ll a=0,ll b=0){x=a,y=b;}};
node mul(node i,node j)
{
    return node(inc(mul(i.x,j.x),mul(mul(i.y,j.y),a)),inc(mul(i.x,j.y),mul(i.y,j.x)));
}
ll power(ll n)
{
    node s(b,1),r(1);
    for(;n;n>>=1,s=mul(s,s))
    if(n&1)
        r=mul(s,r);
    return r.x;
}
void solve()
{
    scanf("%lld%lld%lld%lld",&n,&a,&b,&p);
    printf("%lld\n",power(n));
}
int main()
{
    int T;cin>>T;
    while(T--) solve();
}

原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/11741258.html

时间: 2024-08-30 15:09:40

Comet OJ - Contest #13的相关文章

Comet OJ - Contest #13 「佛御石之钵 -不碎的意志-」(困难版) 并查集

题意 给一个$ n \times m$ 的网格,每个格子里有一个数字,非 \(0\) 即 \(1\),行从上往下依次编号为 \(1, 2, \cdots, n\),列从左往右依次编号为 \(1, 2, \cdots, m\). 给 \(q\) 次操作,每次给定一个以 \((x_1,y_1)\) 为左上角,\((x_2,y_2)\) 为右下角的矩形内所有格子里的数字都变成 \(1\).问每次操作之后,所有数字为 \(1\)的格子构成的四连通块的个数. \(1<=n,m<=1000\) \(1&l

Comet OJ - Contest #13 补题题解

A.险恶的迷宫 题意:在二维平面坐标内,给出一个圆心坐标 (a,b),以及圆的半径 r , 再给出 n 个点的坐标 (x_i,y_i),  求有多少点在圆内. 数据范围:0  <  n  <= 1e5,      0< r , x , y  <=1e9 思路:对于判断距离根据勾股定理: sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)) <= r ,即在圆的范围内.由于此题数据较大,sqrt可能导致精度损失,所以直接开long long 进行平方比较

符文能量(Comet OJ - Contest #8)

给Comet OJ打个小广告,挺好用的,比较简洁,给人感觉很好用 Contest #8是我打的第一场本oj比赛,很遗憾A了前两道傻逼题就没思路了,然后就不打算打了....... https://www.cometoj.com/contest/58/problem/C?problem_id=2760 怎么做啊完全不会啊我那么菜,虽然看到是dp但嫌太麻烦就放弃了: 靠后仔细想了想原来这道题很简单: 结构体node e[];储存ai,bi值(当然你用数组我也不拦着),因为合并的方式很特殊,可以不管合并

Comet OJ - Contest #5

Comet OJ - Contest #5 总有一天,我会拿掉给\(dyj\)的小裙子的. A 显然 \(ans = min(cnt_1/3,cnt_4/2,cnt5)\) B 我们可以感性理解一下,最大的满足条件的\(x\)不会太大 因为当\(x\)越来越大时\(f(x)\)的增长速度比\(x\)的增长速度慢得多 其实可以证明,最大的满足的\(x\)不会超过\(100\) 因为没有任何一个三位数的各位之和大于等于\(50\) 所以我们就直接预处理\(1-99\)所有的合法的 暴力枚举即可 其实

Comet OJ - Contest #10 B

Comet OJ - Contest #10 B 沉鱼落雁 思维题 题意 : 每个数字最多重复出现三次,有n给数字,让你尽可能的使得相同数字之间的最小距离尽可能大 思路 :分三种情况套路 设 a b c 分别代表出现 一次, 两次, 三次 数字的个数 所有元素至多出现一次,答案为 n,题目规定 所有元素至多出现两次, 例如 1 1 2,可以排列成 1 2 1,所以,答案为 1 例如 1 1 2 2 3,可以排列成 1 2 3 1 2,所有 答案为 2 思考后得出,应该尽可能的把 b 个出现两次的

Comet OJ - Contest #7 解题报告

传送门:https://www.cometoj.com/contest/52 A:签到题 题意:多次询问,每次询问给出一个值域区间[l,r],从这区间范围中选出两个整数(可重复),依次求出这俩数的“最大的最小公倍数”.“最小的最小公倍数”.“最大的最大公约数”.最小的最大公约数. 分析:(1)显然,当区间长度为1时,该问题的答案只能是区间中仅有的那个数. (2)当区间的长度大于1时,最大的最小公倍数,lcmmax =lcm(ar,ar-1) = ar * ar-1: 最小的最小公倍数,lcmmi

Comet OJ - Contest #1

A:随便怎么暴力. #include<bits/stdc++.h> using namespace std; #define ll long long #define N 25 char getc(){char c=getchar();while (c!='.'&&c!='#') c=getchar();return c;} int gcd(int n,int m){return m==0?n:gcd(m,n%m);} int read() { int x=0,f=1;char

Comet OJ - Contest #15

https://cometoj.com/contest/79/problem/D?problem_id=4219 题目描述 ※ 简单版与困难版的唯一区别是粗体字部份和 $v$ 的数据范围. 在双 11 时,心慧精品店有个特别的折价活动如下: 首先,我们定义一个正整数为"好的"当且仅当此数仅由数字 1 构成,举例来说 1, 11, 111, 11111 都是「好的」,但 10.123.321 都是「不好的」. 接着,若一个商品原价为 x,若顾客能把 x 表示为 k 个「好的」数字,那么此

Comet OJ - Contest #15题解

A 双十一特惠 (简单版) n  <=  1e19,   1e9 > 1(8) https://www.cometoj.com/contest/79/problem/A?problem_id=4198 #include<bits/stdc++.h> using namespace std; int main(){ int t; cin >> t; while(t--) { int cnt1 = 0; int n;cin >> n; int pr[] = {1