Codeforces Round 1012 (Div. 2)

Codeforces Round 1012 (Div. 2)

A

直接看一看s%(x+y)的余数即可,简单的数学推导

#include<bits/stdc++.h>
using namespace std;
 
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int x,y,a;
        cin>>x>>y>>a;
        int k=a%(x+y);
        if(x>k) cout<<"NO"<<endl;
        else cout<<"YES"<<endl;
    }
    return 0;
}

B

一开始的想法是类似于一个dp看看这个1的左侧和上侧有没有1,如果有是对的不然直接退出

但是可能会跳出,test3就wa了

重新思考一下,发现充要条件是它的上方或左侧全部都是1

#include<bits/stdc++.h>
using namespace std;
const int N=55;
char g[N][N];
 
void slove()
{
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            cin>>g[i][j];
        }
    }
 
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            if(g[i][j]=='1')
            {
                bool st1=1,st2=1;
                for(int k=1;k<=i;k++)
                {
                    if(g[k][j]=='0')
                    {
                        st1=0;
                        break;
                    }
                }
                for(int k=1;k<=j;k++)
                {
                    if(g[i][k]=='0')
                    {
                        st2=0;
                        break;
                    }
                }
                if(st1==0&&st2==0)
                {
                    cout<<"NO"<<endl;
                    return;
                }
            }
        }
    }
    
    cout<<"YES"<<endl;
    return;
}
 
int main()
{
    int t;
    cin>>t;
    while(t--) slove();
    return 0;
}

C

就是动态维护一下起点到哪些桌子点最小的点,和到座位最小的点,可以用小根堆维护

也可以用数组加一个判重数组维护,本人不太会写重载函数所以使用数组

到这里其实就不会写了,剩下的都是看题解补的题

#include<bits/stdc++.h>
using namespace std;
vector<array<int,3>> b;
 
void init()
{
    int m=320;
    for(int i=0;i<m;i++)
    {
        for(int j=0;j<m;j++)
        {
            int x=i*3+1,y=j*3+1;
            b.push_back({x+y-1,x,y});
            b.push_back({x+y,x,y+1});
            b.push_back({x+y,x+1,y});
            b.push_back({x+y+3,x+1,y+1});
        }
    }
    sort(b.begin(),b.end());
}
 
void slove()
{
    int n;
    cin>>n;
    vector<int> a(n);
    for(int i=0;i<n;i++) cin>>a[i];
    int m=sqrt(2*n)+3;
    vector<vector<int>> f(m*3,vector(m*3,0));
    vector<vector<int>> g(m,vector(m,0));
    int k1=0,k0=0;
    for(int i=0;i<n;i++)
    {
        int x,y;
        if(a[i])
        {
            while(f[b[k1][1]][b[k1][2]])k1++;
            x=b[k1][1],y=b[k1][2];
        }
        else
        {
            while(g[b[k0][1]/3][b[k0][2]/3]) k0++;
            x=b[k0][1],y=b[k0][2];
        }
        f[x][y]=1;
        g[x/3][y/3]=1;
        cout<<x<<' '<<y<<endl;
    }
    return;
}
 
int main()
{
    init();
    int q;
    cin>>q;
    while(q--) slove();
    return 0;
}

D

构造题,我们想取一个质数让 i=1时它是质数,但是当i=2时它肯定不是质数了,那么i=3时

希望它是就选取2为1和3的等差中项即可

由于勃兰特---切比雪夫定理和题意我们只需要在n/3何2n/3之间找一个质数即可

#include<bits/stdc++.h>
using namespace std;
const int N=100010;
int prime[N],cnt;
bool st[N];
 
void init()
{
    for(int i=2;i<=N;i++)
    {
        if(st[i]==0) prime[cnt++]=i;
        for(int j=0;prime[j]<=N/i;j++)
        {
            st[prime[j]*i]=true;
            if(i%prime[j]==0) break;
        }
    }
}
 
void slove()
{
    int n;
    cin>>n;
    int l=max(1,n/3);
    int r=(2*n)/3;
    int p=2;
    for(int i=0;i<=cnt;i++)
    {
        if(prime[i]>=l&&prime[i]<=r)
        {
            p=prime[i];
            break;
        }
    }
    
    vector<int> ans;
    ans.push_back(p);
    
    for(int i=1;;i++)
    {
        if(p-i>=1&&p+i<=n)
        {
            ans.push_back(p-i);
            ans.push_back(p+i);
        }
        else if(p-i>=1) ans.push_back(p-i);
        else if(p+i<=n) ans.push_back(p+i);
        else break;
    }
    
    for(int t : ans) cout<<t<<' ';
    cout<<endl;
    return;
}
 
int main()
{
    init();
    //for(int i=0;i<=20;i++) cout<<prime[i]<<endl;
    int t;
    cin>>t;
    while(t--) slove();
    return 0;
}

E1

其实想法和答案以经很接近了,就是找每一个数变为0的步数然后求一个最大值,但是没往深想

其实题干中已经有提示了,题一定有解,sum(b)>=sum(a);说明一个数变为0的步数一定和sum(b)

和sum(a)有关,我们发现经过第一次操作后大数变为其和小数的差,小数直接变为0,然后a错位减

经过一些推导发现什么时候sum(b)>sum(a)时其就为0了

using namespace std;
typedef long long LL;
int n;
 
LL c_sum(LL p[],int l,int r)
{
    if(l>r)return p[n-1]-p[l-1]+p[r];
    else
    {
        if(l-1>=0) return p[r]-p[l-1];
        else return p[r];
    }
}
 
void slove()
{
    int k;
    scanf("%d%d",&n,&k);
    vector<int> a(n);
    vector<int> b(n);
    LL p[n];
    for(int i=0;i<n;i++) scanf("%d",&a[i]);
    for(int i=0;i<n;i++) scanf("%d",&b[i]);
    for(int i=0;i<n;i++)
    {
        p[i]=a[i]-b[i];
        if(i) p[i]+=p[i-1];
    }
    
    vector<int> c(n,1);
    
    for(int i=n-1;i>=0;i--)
    {
        int len=1;
        while(c_sum(p,i,(i+len-1)%n)>0)
        {
            len+=c[(i+len)%n];
        }
        c[i]=len;
    }
    
    int res=-1;
    for(int i=0;i<n;i++) res=max(c[i],res);
    printf("%d\n",res);
    return;
}
 
int main()
{
    int t;
    scanf("%d",&t);
    while(t--) slove();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值