比赛链接: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;
}
C.Binary Search
题解
( 想在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;
}