首页 > 其他分享 >AtCoder Beginner Contest 254(C,D,E,F)

AtCoder Beginner Contest 254(C,D,E,F)

时间:2023-01-15 13:22:33浏览次数:67  
标签:AtCoder gcd Beginner int ai maxn ans include 254

AtCoder Beginner Contest 254(C,D,E,F)

C

C

这个题是给你一个乱序的数组,你可以把ai和ai+k进行交换,我们需要判断是否可以最后变成从小到大的顺序

那么我们可以想到所有下标对k的余数相同的是可以随便交换,那么我们就把同一个余数就把所有的数按照重新到大的顺序,然后我们再进行判断,如果可以就是yes,否则就是No

#include <algorithm>
#include <iostream>
#include<vector>
#include <string>
#include <set>
using namespace std;
#define int long long 
const int maxn=2e5+10;
int a[maxn],ans[maxn];
int n,k;
signed main ()
{
    cin>>n>>k;
    for (int i=1;i<=n;i++)
    {
        cin>>a[i];
    }
    for (int i=0;i<k;i++)
    {
        vector<int>st;
        for (int j=i+1;j<=n;j+=k)
        {
            st.push_back(a[j]);
        }
        sort(st.begin(),st.end());
        int now=i+1;
        for (auto x:st)
        {
            ans[now]=x;
            now+=k;
        }
    }
    bool yes=true;
    for (int i=2;i<=n;i++)
    {
        if (ans[i-1]>ans[i])
        {
            yes=false;
            break;
        }
    }
    if (yes)
    {
        cout<<"Yes\n";
    }
    else 
    {
        cout<<"No\n";
    }
    system ("pause");
    return 0;
}

D

D

这一道题的大意是给你一个n的网格,我们要找到一个点i,j,其中iXj是平方数的个数

对于一个数,我们都可以把一个数x变成prei^iz* prej^k(pre是质数,对于每一个数,都是可以分解成若干个质数),对于是一个平方数,那么那些质数的幂次一定是偶数的

然后我们知道1到nXn一定有1,到n的平方数

那么我们只要列举1到n,记录i的平方时有几种

我们先判断它是否可以分解(质数一定是只有一个,i,i)

然后我们分解x,如果中间的质数出现了奇数次幂,那么我们ans*=pre,那么我们求出的数量就和这个奇数次幂的乘积有关,cnt=sqrt((x-1)/ans),然后我们可以求出1到n的平方数的总个数

#include <iostream>
#include <string>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn=2e5+10;
#define int long long 
int pre[maxn],num[maxn];
int n;
int dp[maxn];
void init(int x)
{
    pre[1]=1;
    for (int i=2;i<=x;i++)
    {
        if (pre[i]) continue;
        for (int j=i;j<=x;j+=i)
        {
            pre[j]=i;
        }
    }
    return ;
}
signed  main ()
{
    cin>>n;
    init(n);
    int sum=0;
    for (int i=1;i<=n;i++)
    {
        int tmp=0;
        if (pre[i]!=i)
        {
           int x=i,ans=1;
           while (pre[x]!=x)
           {
            int now=pre[x],way=0;
            while (pre[x]==now)
            {
                x/=pre[x];
                way++;
            }
            if (way&1)
            {
                ans*=now;
            }
           }
           ans*=pre[x];
        }
        sum+=tmp*2+1;
    }
    cout<<sum<<'\n';
    system ("pause");
    return 0;
}

E

E

这一道题的大意是我们需要建一个图,然后会有q次询问,我们要知道和x之间的距离小于等于k的所有顶点的和

对于这一题题目告诉我们每一个点的度都会小于等于3,那么我们就直接搜索了

#include <iostream>
#include <string>
#include <cstring>
#include <vector>
#include <queue>
using namespace std;
#define int long long 
const int maxn=2e5+10;
vector<int>g[maxn];
int vis[maxn];
int bfs(int n,int k)
{
    int ans=0;
    queue<pair<int,int>>q;
    vector<int>v;
    q.push({n,0});
    while (!q.empty())
    {
        int now=q.front().first;
        int w=q.front().second;
        q.pop();
        if (vis[now]) continue;
        ans+=now;
        v.push_back(now);
        vis[now]=1;
        if (w==k) continue;
        for (int i=0;i<g[now].size();i++)
        {
            int to=g[now][i];
            q.push({to,w+1});
        }
    }
    for (int i=0;i<v.size();i++)
    {
        vis[v[i]]=0;
    }
    return ans;
}
signed  main ()
{
    int n,m;
    cin>>n>>m;
    for (int i=1;i<=m;i++)
    {
        int x,y;
        cin>>x>>y;
        g[x].push_back(y);
        g[y].push_back(x);
    }
    int q;
    cin>>q;
    while (q--)
    {
        int x,k;
        cin>>x>>k;
        int ans=bfs(x,k);
        cout<<ans<<'\n';
    }
    system ("pause");
    return 0;
}

F

F

这一题大意是给你一个nXn的网格,每一个格子里都有一个数字,每一个i,j的值就是ai+bj.然后我们还是会进行q次询问,每次都会告诉你一个四边形块,我们要知道的是这一块的所有的数的gcd

对于这一题,我们要知道 如果a和b互质,那么a+b和a互质,和b互质,abs(a-b)和a,b也互质

那么gcd(a,b)=gcd(a,abs(a-b))

那么我们对于gcd(ai+bj,ai+bj+1,ai+bj+2)这一行,可以后面的都可以转换成

gcd(ai+bj,bj+1-bj,bj+2-bj+1) 后面的一项减去前面的那一项

对于下一步

我们可以先看到下面,对于这一个网格

a1+b1 a1+b2 a1+b3 a1+b4 a1+b5
a2+b1 a2+b2 a2+b3 a2+b4 a2+b5
a3+b1 a3+b2 a3+b3 a3+b4 a3+b5
a4+b1 a4+b2 a4+b3 a4+b4 a4+b5
a5+b1 a5+b2 a5+b3 a5+b4 a5+b5

gcd(ai+b1,ai+b2,ai+b3,ai+b4,ai+b5)变成gcd(ai+b1,b2-b1,b3-b2),

我们可以发现从1,2到1,5的之间的差值,和2,2和2,5是一样的,

那么我们只要求当i=1的时候,那么我们可以知道 1,2到5,5 这一块的gcd,

但是我们并没有加上a1+bi第一列,

那么我们可以换一个方向

gcd(a1+bi,a2+bi,a3+bi,a4+bi,a5+bi),同样可以转换成

gcd(a1+bi,a2-a1,a3-a2,a4-a3,a5-a4)

还是当i=1时,我们可以知道 2,1到5,5 这一块的gcd(会有重复的,但是也覆盖了一部分),但是我们还有一个没有放进去,那就是a1+b1,那我们就自己加进去

我前面表达的可能不太准确,可以看这个大佬,里面有图

然后我们只要求差分的gcd,但是我们怎么求这一段差分的gcd呢

我们这里用了线段树

具体看代码

#include <iostream>
#include <string>
#include <algorithm>
#include <cmath>
using namespace std;
#define int long long 
const int maxn=2e5+10;
int a[2][maxn],d[2][maxn],tr[2][maxn<<2];
void build(int now,int l,int r)
{
    if (l==r)
    {
        tr[0][now]=d[0][l];//0是a的差分,1是b的差分
        tr[1][now]=d[1][l];
        return ;
    }
    int mid=(l+r)>>1;
    build(now<<1,l,mid);
    build(now<<1|1,mid+1,r);
    for (int i=0;i<=1;i++)
    {
        tr[i][now]=__gcd(tr[i][now<<1],tr[i][now<<1|1]);
    }
    return ;
}
int query(int now,int l,int r,int L,int R,int way)
{
    if (L<=l&&r<=R)
    {
        return tr[way][now];
    }
    int mid=(l+r)>>1,ans=0;
    if (L<=mid)
    {
        ans=query(now<<1,l,mid,L,R,way);
    }
    if (R>mid)
    {
        ans=__gcd(ans,query(now<<1|1,mid+1,r,L,R,way));
    }
    return ans;
}
signed main ()
{
    int n,q;
    cin>>n>>q;
    for (int i=0;i<=1;i++)
    {
        for (int j=1;j<=n;j++)
        {
            cin>>a[i][j];
            d[i][j]=abs(a[i][j]-a[i][j-1]);
        }
    }
    build(1,1,n);
    while (q--)
    {
        int h1,h2,w1,w2;
        cin>>h1>>h2>>w1>>w2;
        int ans=a[0][h1]+a[1][w1];
        if (h1!=h2)
        {
            ans=__gcd(ans,query(1,1,n,h1+1,h2,0));
        }
        if (w1!=w2)
        {
            ans=__gcd(ans,query(1,1,n,w1+1,w2,1));
        }
        cout<<ans<<'\n';
    }
    system ("pause");
    return 0;
}

标签:AtCoder,gcd,Beginner,int,ai,maxn,ans,include,254
From: https://www.cnblogs.com/righting/p/17053360.html

相关文章

  • AtCoder Regular Contest 153
    喜提全场独一无二的score!ATC还是很友善的,如果每题等分就寄了A签到B真的是凭着实力不会做的呀。。。太菜了发现两维可以分别做,所以考虑一维的情况,然而并不会对于两......
  • Atcoder abc275F
    Atcoderabc275F题意:给出一个长度为\(n\)的数组\(A=(a_1​,a_2​,…,a_N)\),问是否能通过删掉一些子段使剩下的数之和为\(q\)。若可以,求出最小操作次数,否则输出−1......
  • AtCoder Beginner Contest 282 G - Similar Permutation
    套路题题意求有多少个\(1\)到\(n\)的排列满足恰有\(k\)对在排列中相邻的数满足前小于后\(2\leqn\leq500,0\leqk\leq(n-1)\)思路f[i][j][k]表示已经......
  • AtCoder Beginner Contest 134
    AtCoderBeginnerContest134https://atcoder.jp/contests/abc134A-Dodecagon#include<bits/stdc++.h>usingnamespacestd;intmain(){inta;cin......
  • abc254 F - Rectangle GCD
    题意:给定等长的正整数组\(a[],b[]\),它们确定了一个矩阵\(A_{i,j}=a_i+b_j\)。\(q\)次询问,回答矩阵中一个矩形区域内所有数的\(\gcd\)\(n,q\le2e5\)思路:差分,绝对......
  • AtCoder Beginner Contest 042
    A-IrohaandHaiku(ABCEdition)#include<bits/stdc++.h>usingnamespacestd;int32_tmain(){inta=2,b=1;for(inti=1,x;i<=3;i++......
  • AtCoder Beginner Contest 133
    AtCoderBeginnerContest133https://atcoder.jp/contests/abc133A-TorT#include<bits/stdc++.h>usingnamespacestd;intmain(){inta,b,n;ci......
  • Arcgis字段长度最大为254?
    使用数据库!参考:https://www.jianshu.com/p/9b854b1fb1e7......
  • AtCoder Beginner Contest 171
    A-αlphabet(abc171a)题目大意给定一个字母,其大写字母则输出A,否则输出a。解题思路isupper函数或者在'A'与Z之间即为大写字母。神奇的代码#include<bits/stdc+......
  • AtCoder284 D - Happy New Year 2023
    AtCoder284D-HappyNewYear2023[Editorial](Editorial-AtCoderBeginnerContest284)Youaregivenapositiveinteger\(N\).Itisknownthat\(N\)canbe......