Codeforces Round #678 (Div. 2)【ABC】

比赛链接:https://codeforces.com/contest/1436

A.Reorder

题解

经过模拟计算,观察到
\(\sum_{i=1}^n \sum_{j=i}^n \frac{a_j}{j}=\sum_{i=1}^n a_i\)
判断每个n个数的和sum与m是否相等即可

代码

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int main()
{
    ios::sync_with_stdio(false);//关闭cin与scanf同步
    cin.tie(nullptr);
    int t;cin>>t;
    while(t--)
    {
        int n,m,x,sum=0;
        cin>>n>>m;
        for(int i=0;i<n;i++)
        {
            cin>>x;
            sum+=x;
        }
        if(sum==m)
            cout<<"YES"<<endl;
        else
            cout<<"NO"<<endl;
    }
    return 0;
}

B.Yet Another Bookshelf

题意

\(要求构造一个n*n的矩阵满足:\\ 1.矩阵的所有元素均为非负整数,不超过10^5.\\ 2.矩阵所有的元素均为合数\\ 3.矩阵中各行个列的和均为素数\)

题解

\( 比赛的时候写的贼麻烦.\\ 法一.\\ 线性筛法求质数,check函数判是不是合数。\\ 在n*n的矩阵中,让(n-1)*(n-1)的矩阵全填写1,特殊处理第n行,第n列,再特判(n,n)元素填哪个\)

代码

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;

const int N=1e5+10;

int p[N],cnt,st[N];
int a[N];
void init(int n)
{
    for(int i=2;i<=n;i++)
    {
        if(!st[i])
            p[cnt++]=i;
        for(int j=0;p[j]<=n/i;j++)
        {
            st[i*p[j]]=1;
            if(i%p[j]==0)
                break;
        }
    }
}

bool check(int x)
{
    if (x < 2) return false;
    for (int i = 2; i <= x / i; i ++ )
        if (x % i == 0)
            return false;
    return true;
}


int main()
{
    int t;cin>>t;
    init(10000);
    for(int j=1;j<=1000;j++)
    {
        if(p[j]>100)
        {
            a[j]=p[j];
        }
    }
    while(t--)
    {
        int n;cin>>n;
        ll ans;
        for(int i=1;i<=1000;i++)
        {
            if((a[i]-n+1)>=1&&!check(a[i]-n+1))//这个数不是质数
            {
                ans=a[i]-n+1;
                break;
            }
        }
        ll res;
        for(int k=1;k<=1000;k++)
        {
            if(check((ans*(n-1)+k))&&!check(k))
            {
                res=k;
                break;
            }
            
        }
        
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                if(i==n&&j==n)
                {
                    cout<<res<<" ";
                }
                else if(i==n)
                    cout<<ans<<" ";
                else if(j==n)
                    cout<<ans<<endl;
                else
                    cout<<1<<" ";
            }
        }
        //大于n-1的最小的质数
    }
    return 0;
}
/*
1 1 1 1e5-1
*/

法二:
\(沿对角线填2*2的1矩阵(构造)\)

1 1
1 1
    1 1
    1 1  (还不对)
1 1 
1 1 1
  1 1 1
    1 1 1
      1 1 1
        1 1
           (对了)

代码

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;

const int N=1100;
int a[N][N],n;

void init()
{
    int flag=false;
    for(int i=1;i<=N/10;i++)
    {
        if(flag==false)
        {
            for(int j=i;j<=i+1;j++)
            {
                a[i][j]=1;
            }
            flag=true;
        }
        else
        {
            for(int j=i-1;j<=i;j++)
                a[i][j]=1;
            i--;
            flag=false;
        }
    }
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t;cin>>t;
    init();
    while(t--)
    {
        cin>>n;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                cout<<a[i][j]<<" ";
            }
            cout<<endl;
        }
        
    }
    return 0;
}

题解

\( 想在pos位置上找到x,\\ 如果二分的位置小于pos的话,说明这个位置的数应该<x ,sma++\\ 如果二分的位置大于pos的话,说明这个位置的数应该>x ,big++\\ 对于所有的全排列\\ 从n-x(1~n中所有>x的数)选big的全排列\\ 从x-1(1~n中所有<x的数)选sma的全排列\\ pos位置上填x\\ 剩下的所有数other全排列(n-big-sma-1)\\ ans=A_{n-x}^{big} * A_{x-1}^{sma} *A_{other}^{other}\\ 注意:一定要用题干中给定的二分方法来查找,否则即使方法正确,再判断边界时依然会有问题\\ 比如 1 1 0 (在0位找1,0<=pos<=n-1) 正确答案为0,y总模板得1 \)

代码

#include<iostream>
#include<algorithm>
using namespace std;

const int mod=1e9+7;
typedef long long ll;
ll n,x,pos;

ll A(int n,int m)
{
    ll res=1;
    for(int i=0;i<m;i++)
    {
        res=res*(n-i)%mod;
    }
    return res;
}

int main()
{
    cin>>n>>x>>pos;
    int l=0,r=n,small=0,big=0;
    while(l<r)
    {
        int mid=l+r+1>>1;
        if(mid<=pos)
        {
            if(mid!=pos)
                small++;
            l=mid;
        }
        else
        {
            big++;
            r=mid-1;
        }
    }
    int other=n-big-small-1;
    // cout<<A(n-x,big)<<endl;
    // cout<<A(x-1,small)<<endl;
    // cout<<A(other,other)<<endl;
    cout<<A(n-x,big)*A(x-1,small)%mod*A(other,other)%mod;
}
posted @ 2020-11-01 17:26  30天CF上蓝!!!  阅读(123)  评论(0编辑  收藏  举报