菜的真实,感觉没救了
A.Array Rearrangment
//#pragma comment(linker, "/STACK:102400000,102400000")
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int>pii;
//#define int ll
#define ff first
#define ss second
#define debug(x) std:: cerr << #x << " = " << x << std::endl;
const int maxn=2e5+10,inf=0x3f3f3f3f,mod=1000000007;
const ll INF=0x3f3f3f3f3f3f3f3f;
const double eps=1e-9;
int a[maxn],b[maxn];
signed main(signed argc, char const *argv[])
{
int t,n,x;
cin>>t;
while(t--)
{
cin>>n>>x;
bool ok=1;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1;i<=n;i++)
cin>>b[i];
sort(a+1,a+n+1);
sort(b+1,b+n+1,greater<int>());
for(int i=1;i<=n;i++)
if(a[i]+b[i]>x)
ok=0;
cout<<(ok?"Yes":"No")<<endl;
}
return 0;
}
B.Elimination
//#pragma comment(linker, "/STACK:102400000,102400000")
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int>pii;
//#define int ll
#define ff first
#define ss second
#define debug(x) std:: cerr << #x << " = " << x << std::endl;
const int maxn=2e5+10,inf=0x3f3f3f3f,mod=1000000007;
const ll INF=0x3f3f3f3f3f3f3f3f;
signed main(signed argc, char const *argv[])
{
int t,a,b,c,d;
cin>>t;
while(t--)
{
cin>>a>>b>>c>>d;
cout<<max(a+b,c+d)<<endl;
}
return 0;
}
C.Division
题意
给定一对整数 p p p与 q q q,求最大的整数 x x x,使 p p p能被 x x x整除, x x x不能被 q q q整除, 1 ≤ p ≤ 1 0 18 , 2 ≤ q ≤ 1 0 9 1\le p\le 10^{18},2\le q\le 10^{9} 1≤p≤1018,2≤q≤109。
思路
当你开始尝试对
p
p
p和
q
q
q进行质因子分解时就会发现,只要
x
x
x质因子分解后存在一种质因子小于
q
q
q分解后的数量,那么此时
x
x
x就不能被
q
q
q整除。
所以我们枚举
q
q
q质因子分解后的每个质因子,记录数量为
c
c
c,并且控制
x
x
x中含有
c
−
1
c-1
c−1个该质因子,暴力计算并记录最大的答案即可。
//#pragma comment(linker, "/STACK:102400000,102400000")
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+10,inf=0x3f3f3f3f,mod=1000000007;
bool prime(ll x)
{
if(x <= 1)
return 0;
if( x == 2 || x == 3 || x == 5 )
return 1;
if( x%2 == 0 || x%3 == 0 ) /*判断是否为2,3的倍数*/
return 0;
ll lim=sqrt((float)x)+1;
for(ll i=6; i<=lim; i += 6 ){//这里可能会有错
if( x % (i-1) == 0 || x % (i+1) == 0 )
return 0;
}
return 1;
}
signed main(signed argc, char const *argv[])
{
std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
ll t,p,q;
cin>>t;
while(t--)
{
cin>>p>>q;
ll ans=1;
if(p<q||p%q)
ans=p;
else if(prime(q))
{
while(p%q==0&&p>1)
p/=q;
ans=p;
}
else{
ll now=p/q,tmp=q;
vector<ll>f;
// map<ll,int>mp;
for(ll i=2;i*i<=tmp;i++)
{
if(tmp%i==0)
{
f.push_back(i);
while(tmp%i==0)
tmp/=i;
}
}
if(tmp>1)
f.push_back(tmp);
for(ll &x:f)
{//此时的x控制为mp[x]-1个
ll now=q/x,n1=p/q;
while(n1%x==0)
n1/=x;
now*=n1;
ans=max(ans,now);
}
}
cout<<ans<<endl;
}
return 0;
}
D.Divide and Sum
题意
给你
2
n
2n
2n个整数,你要把它分为数量相等的两组
p
p
p与
q
q
q,
p
p
p按非递减排序,
q
q
q按非递增排序。
对于所有的合法情况,计算每种情况
∑
i
=
1
n
∣
p
i
−
q
i
∣
\sum\limits_{i=1}^{n}{|p_i-q_i|}
i=1∑n∣pi−qi∣的和,对998244353取模。
思路
大概都是猜结论过的吧……赛中心态崩了,赛后一发AC。
若将给定数从大到小排序,记录前半段为
L
L
L,后半段为
R
R
R。
一个结论是,对于所有情况,
p
p
p与
q
q
q中的相同位置的两个数字必定一个来自于
L
L
L,另一个来自于
R
R
R。
因此对于每一对,都是大的减去小的;对于两个数组整体来看,就是
R
R
R部分减去
L
L
L部分,这个值对所有情况等是恒定的。
因此只需用这个定值乘以情况数
C
(
2
n
,
n
)
=
(
2
n
)
!
n
!
n
!
C(2n,n)=\dfrac{(2n)!}{n!n!}
C(2n,n)=n!n!(2n)!即为答案
证明
假设
p
p
p与
q
q
q中存在一个下标
i
i
i,
p
i
p_i
pi与
q
i
q_i
qi全部来自于
L
L
L。
那么因为
p
p
p单调递减,所以
p
i
p_i
pi前面有
i
−
1
i-1
i−1个数小于等于
p
i
p_i
pi;同理,
q
i
q_i
qi后面有
n
−
i
n-i
n−i个数小于等于
q
i
q_i
qi。
那么因为一个数只能分到一个集合里,所以包括
p
i
p_i
pi与
q
i
q_i
qi,一共有至少
n
+
1
n+1
n+1个数在
L
L
L集合,所以下标相同的
p
i
p_i
pi与
q
i
q_i
qi不能来自于同一部分。
代码
//#pragma comment(linker, "/STACK:102400000,102400000")
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define debug(x) std:: cerr << #x << " = " << x << std::endl;
const int maxn=3e5+10,inf=0x3f3f3f3f,mod=998244353;
ll qmod(ll a,ll b,ll mod) //快速幂
{
ll ans=1;
a=a%mod;
while(b)
{
if(b&1)
ans=ans*a%mod;
a=a*a%mod;
b>>=1;
}
return ans;
}
ll a[maxn],fac[maxn]={1,1};
signed main(signed argc, char const *argv[])
{
std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#ifdef DEBUG
freopen("input.in", "r", stdin);
// freopen("output.out", "w", stdout);
#endif
ll n,ans=0;
cin>>n;
for(int i=2;i<=2*n;i++)
fac[i]=(fac[i-1]*i)%mod;
for(int i=1;i<=2*n;i++)
cin>>a[i];
sort(a+1,a+2*n+1,greater<ll>());
ll lamb=fac[2*n]*qmod(fac[n],mod-2,mod)%mod*qmod(fac[n],mod-2,mod)%mod;
cerr<<"lamb = "<<lamb<<endl;
for(ll i=1;i<=n;i++)
{
ans+=(a[i]-a[n+i])*lamb%mod;
ans%=mod;
}
cout<<ans<<endl;
return 0;
}
E.Team-Building
题意
n个学生被分为k个小组,有m对熟人。
要选出两个小组,将这些人分成两个小队,要求每个小队内部没有熟人。
求合法的小组对数。