鄙人不才,此中鄙陋甚多,望海涵!!!
C题(具体题目直接去官网看吧,英文题目放在这里有些不和谐)
前置知识:线性筛,分解质因数
题目大意:要求找到一个最大的X满足P是X的倍数,而X不是Q的倍数!
1.首先当(p%q!=0),那么最大的x就一定是p了
2.当(p%q==0)时,我们就要具体去分析了,当p是q的倍数时,那么q分解出的质因子必然都是在p中出现过的,我们其实只要想一个恰当的方法处理好这些共同的质因子,就一定能从p的质因子找到一个组合保证不是q的倍数而且是最大的,这里我们先给出这个方法,我们只要保证p中与q对应的某一个质因子次幂比在q中对应该质因子的次幂少一即可,这样就满足了肯定不是倍数的关系了,再去满足最大,那么我们就要保证在满足次幂减一的这个条件时代价最小,就存下来代价找到最小的即可!
C++ Code
#include<iostream>
using namespace std;
typedef long long LL;
const int N=40010;
int primes[N],cnt;
bool st[N];
LL prs[N],pos[N];
void get_primes()
{
for(int i=2;i<N;i++)
{
if(!st[i]) primes[cnt++]=i;
for(int j=0;primes[j]*i<N;j++)
{
st[primes[j]*i]=true;
if(i%primes[j]==0) break;
}
}
}
int main()
{
get_primes();
int T;
cin>>T;
LL p,q;
while(T--)
{
scanf("%lld%lld",&p,&q);
if(p%q) printf("%lld\n",p);
else
{
int w=0;
for(int i=0;i<cnt && primes[i]<=q/primes[i];i++)
{
if(q%primes[i]==0)
{
pos[w]=1;
prs[w]=primes[i];
while(q%primes[i]==0)
{
q/=primes[i];
pos[w]*=primes[i];
}
w++;
}
}
if(q!=1) pos[w]=q,prs[w++]=q;
LL minv=1e18,tmp=p;
for(int i=0;i<w;i++)
{
LL o=prs[i];
p/=pos[i];
while(p%prs[i]==0)
{
p/=prs[i];
o*=prs[i];
}
minv=min(o,minv);
}
printf("%lld\n",tmp/minv);
}
}
return 0;
}
D题
前置知识:费马定理,快速幂求解逆元
题目大意:从一个长度为2*n的序列分为2个长度为n的序列,其中一个升序一个降序,所有对应的子序列的对应数绝对值差值的总和!
此题关键就在于发现分出的2个序列分别升序与降序排列后对应数差值总和是相同的,我们记为sum,所以我们只需要知道选出的序列有多少种情况即可,易知为C(2*n,n)
!
C++Code
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
const int mod=998244353,N=300010;
LL a[N];
LL qmi(LL a,LL b)
{
LL res=1;
while(b)
{
if(b&1) res=(res*a)%mod;
a=(a*a)%mod;
b>>=1;
}
return res;
}
LL C(int x,int y)
{
LL res=1,nes=1;
for(int i=1,j=x;i<=y;i++,j--)
{
res=(res*j)%mod;
nes=(nes*i)%mod;
}
nes=qmi(nes,mod-2);
return (res*nes)%mod;
}
int main()
{
int n;
cin>>n;
for(int i=0;i<2*n;i++) scanf("%lld",&a[i]);
sort(a,a+2*n);
LL sum=0;
for(int i=0;i<n;i++) sum=(sum+a[i+n]-a[i])%mod;
LL ans=(C(2*n,n)*sum)%mod;
cout<< ans <<endl;
return 0;
}
蒟蒻
您是大佬!!!
Tql
hhh,我是蒟蒻!