C S P − S 2024 模拟赛 3 补题报告 2024 年 7 月 23 日 − 2023 年 7 月 25 日 b y 邓时飏 CSP \ - \ S \ \ 2024 \ \ 模拟赛3 \ \ 补题报告 \\ 2024年7月23日 - 2023年7月25日 \\ by \ \ \ 邓时飏 CSP − S 2024 模拟赛3 补题报告2024年7月23日−2023年7月25日by 邓时飏
一、做题情况
-
第一题比赛 80 80 80 / 100 100 100 ,赛后通过
-
第二题比赛 0 0 0 / 100 100 100 ,赛后通过
-
第三题比赛 0 0 0 / 100 100 100 ,赛后通过
-
第四题比赛 0 0 0 / 100 100 100 ,赛后通过
-
比赛得分 0 0 0 / 400 400 400 ,赛后补题 400 400 400 / 400 400 400
二、题解报告
T1:
题面:
做法:
枚举两个点,确定另外两个点。
附:AC代码
#include<bits/stdc++.h>
using namespace std;
int x[3005],y[3005],vis[5005][5005];
int main(){
int n,maxn=0;
cin>>n;
for(int i=1;i<=n;i++){
cin>>x[i]>>y[i];
vis[x[i]][y[i]]++;
}
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++){
double nx=(x[i]+x[j])/2.0,ny=(y[i]+y[j])/2.0;
double a=nx-ny,b=nx+ny;
if(a-int(a)!=0||b-int(b)!=0) continue;
int dx=int(a)+y[i],dy=int(b)-x[i],xx=int(a)+y[j],yy=int(b)-x[j];
if(dx<0||dy<0||xx<0||yy<0||dx>5000||dy>5000||xx>5000||yy>5000) continue;
if(vis[dx][dy]&&vis[xx][yy]) maxn=max(maxn,int((dx-x[i])*(dx-x[i])+(dy-y[i])*(dy-y[i])));
}
cout<<maxn;
return 0;
}
T2:
题面:
做法:
求从一个序列中有序地取出k个数后的最大值,该值为每个数减去其前面所有数的绝对值之和。
首先对原序列排序。排序不影响答案。
接着,显然取出最大和最小值一定没错的。
再依次从没有取出的数中,取最小的和最大的放在取出的序列中间。
这个又为什么是对的呢?
考虑现在要取出的数放到取出的序列中间时,左右各有 l s i z e , r s i z e lsize,rsize lsize,rsize个数,左右数字和各为 l s u m , r s u m lsum,rsum lsum,rsum。
那么插入这个数 x x x对答案的贡献为
(
r
s
u
m
−
r
s
i
z
e
∗
x
)
+
(
l
s
i
z
e
∗
s
u
m
−
l
s
u
m
)
(rsum-rsize*x)+(lsize*sum-lsum)
(rsum−rsize∗x)+(lsize∗sum−lsum)
提取
(
r
s
u
m
−
l
s
u
m
)
−
(
r
s
i
z
e
−
l
s
i
z
e
)
∗
x
(rsum-lsum)-(rsize-lsize)*x
(rsum−lsum)−(rsize−lsize)∗x
这个式子同时解释了为什么整个取出序列必须时升序的,且要从最大值和最小值开始取数,以及为什么要尽量保持左右数的数的数量平均。
附:AC代码
#include <bits/stdc++.h>
#define IL inline
#define re register
#define LL long long
#define ULL unsigned long long
#define debug printf("Now is %d\n",__LINE__);
using namespace std;
template<class T>inline void read(T&x) {
char ch=getchar();
int fu;
while(!isdigit(ch)&&ch!='-') ch=getchar();
if(ch=='-') fu=-1,ch=getchar();
x=ch-'0';
ch=getchar();
while(isdigit(ch)) {
x=x*10+ch-'0';
ch=getchar();
}
x*=fu;
}
inline int read() {
int x=0,fu=1;
char ch=getchar();
while(!isdigit(ch)&&ch!='-') ch=getchar();
if(ch=='-') fu=-1,ch=getchar();
x=ch-'0';
ch=getchar();
while(isdigit(ch)) {
x=x*10+ch-'0';
ch=getchar();
}
return x*fu;
}
int G[55];
template<class T>inline void write(T x) {
int g=0;
if(x<0) x=-x,putchar('-');
do {
G[++g]=x%10;
x/=10;
} while(x);
for(int i=g; i>=1; --i)putchar('0'+G[i]);
putchar('\n');
}
LL a[1000010],ansxb[1000][1000],ans[1000],n;
int main() {
n=read();
for(int i=1; i<=n; i++) a[i]=read();
sort(a+1,a+n+1);
if(n<=5) {
do {
re LL now=0;
for(re int i=1; i<=n; i++) {
for(re int j=1; j<=i; j++) now+=abs(a[i]-a[j]);
if(now>ans[i]) {
ans[i]=now;
for(int j=1; j<=i; j++) ansxb[i][j]=a[j];
}
}
} while(next_permutation(a+1,a+n+1));
for(re int i=1; i<=n; i++) cout<<ans[i]<<endl;
} else {
cout<<0<<endl;
LL ans=a[n]-a[1];
LL l=2,r=n-1,lsum=a[1],lsize=1,rsum=a[n],rsize=1;
cout<<ans<<endl;
for(re int i=3; i<=n; i++) {
if(i&1) {
ans+=rsum-rsize*a[l]-lsum+lsize*a[l];
lsum+=a[l];
lsize++;
l++;
} else {
ans+=rsum-rsize*a[r]-lsum+lsize*a[r];
rsum+=a[r];
rsize++;
r--;
}
write(ans);
}
}
return 0;
}
T3:
题面:
做法:
附:AC代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1005;
const int P[11] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31};
int n, a[N], p[N], q[N];
int dp[1 << 11], g[1 << 11];
vector<int> vec[N];
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int test;
cin >> test;
while (test --) {
for (int i = 1; i <= 1000; i++) vec[i].clear();
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
q[i] = a[i];
p[i] = 0;
for (int k = 0; k < 11; k++) {
if (q[i] % P[k] == 0) {
p[i] |= 1 << k;
while (q[i] % P[k] == 0) q[i] /= P[k];
}
}
vec[q[i]].push_back(i);
}
fill(dp + 1, dp + (1 << 11), -1);
dp[0] = 0;
for (int i: vec[1]) {
copy(dp, dp + (1 << 11), g);
for (int j = 0; j < (1 << 11); j++) {
if (dp[j] != -1 && (j & p[i]) == 0) {
auto &v = g[j | p[i]];
v = max(v, dp[j] + 1);
}
}
copy(g, g + (1 << 11), dp);
}
for (int k = 2; k <= 1000; k++) {
if (vec[k].size()) {
copy(dp, dp + (1 << 11), g);
for (int i: vec[k]) {
for (int j = 0; j < (1 << 11); j++) {
if (dp[j] != -1 && (j & p[i]) == 0) {
auto &v = g[j | p[i]];
v = max(v, dp[j] + 1);
}
}
}
copy(g, g + (1 << 11), dp);
}
}
int ans = 1;
for (int i = 0; i < (1 << 11); i++) ans = max(ans, dp[i]);
cout << ans << endl;
}
return 0;
}
T4:
题面:
做法:
附:AC代码
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define int long long
using namespace std;
const int inf=0x3f3f3f3f;
const ll inff=0x3f3f3f3f3f3f3f3f;
const double PI=3.1415926535897932385;
const double ol=1e6+5;
const int N=1e7+5;
const int M=1e9+7;
const ull P=131;
const int mod=1e9+7;
const int MOD=1e9+7;
const double eps=1e-5;
int read() {
int w = 0, h = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {
if (ch == '-')h = -h;
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
w = w * 10 + ch - '0';
ch = getchar();
}
return w * h;
}
void write(int x) {
if (x > 9) write(x / 10);
putchar(x % 10 + '0');
}
void writeln(int x) {
write(x);
puts("");
}
void writech(int x) {
write(x);
putchar(' ');
}
ll lowbit(ll x) {
return x&-x;
}
ll gcd(ll a,ll b) {
return b==0?a:gcd(b,a%b);
}
ll lcm(ll a,ll b) {
return a/gcd(a,b)*b;
}
ll exgcd(ll a,ll b,ll &x,ll &y) {
if(!b) {
x=1,y=0;
return a;
}
ll d=exgcd(b,a%b,y,x);
y-=a/b*x;
return d;
}
ll ksm(ll a,ll b,ll c) {
ll sum=1;
a%=c;
while(b) {
if(b&1)sum=sum*a%c;
a=a*a%c;
b>>=1;
}
return sum;
}
ll addm(ll a,ll b,ll c) {
return (a%c+b%c)%c;
}
ll faddm(ll a,ll b) {
return (((a%b)+b)%b);
}
ll fact[N],infact[N];
void init(ll n) {
fact[0]=1;
for(int i=1; i<=n; i++) fact[i]=(fact[i-1]*i)%mod;
infact[n]=ksm(fact[n],mod-2,mod);
for(int i=n-1; i>=0; i--) infact[i]=infact[i+1]*(i+1)%mod;
}
ll cmb( ll a , ll b ) {
if(b>a) return 0 ;
return (((fact[a]*infact[a-b])%mod)*infact[b])%mod ;
}
int a[N],v[N];
int inv(int x) {
return ksm(x,M-2,M);
}
void solve() {
int n,m,dmx=0;
cin>>n>>m;
init(N-1);
for(int i=1; i<=n; i++) cin>>a[i];
for(int i=2; i<=n; i++) dmx=max(dmx,a[i-1]-a[i]);
for(int i=0; i<=dmx; i++) v[i]=ksm(m,i,M)*inv(ksm(m-1,i,M))%M;
int ans=1;
for(int i=1; i<=a[n]; i++) ans=ans*m%M;
for(int i=n-1; i>=1; i--) {
int d=a[i]-a[i+1],cnt=0;
for(int j=0; j<=d; j++) {
int k=cmb(a[i]-j-1,a[i+1]-1);
cnt+=v[j]*k;
cnt%=M;
}
cnt=cnt*ksm(m-1,d,M)%M;
ans=ans*cnt%M;
}
cout<<ans<<"\n";
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T=1;
while(T--) solve();
}
四、赛后总结
提升实力,控制时间。