2026 · CSP-S · 二十连测 · 模拟三 题解

T1

这个数的倍数比较特别。你只需要保证每一位之和恰好为它的倍数即可而又由于每一位都至少有一个所以,我们针对所有树枝和的余树减掉即可。

持有这种方案,只需减一位,而其他方案至少需要减两位,故这方案最优。

接下来问每一位直接2分即可。

注意,这道题少开 long long

代码

点击查看代码
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f3f3f3f3f
#define int long long
#define endl '\n'
using namespace std;
const int maxn=1e6+5;
int a[maxn];
signed main()
{
	freopen("num.in","r",stdin);
	freopen("num.out","w",stdout);
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	int n,q;cin>>n>>q;
	int sum=0;
	for(int i=0;i<n;i++) cin>>a[i],sum+=i*a[i];
	if(sum%(n-1)) a[sum%(n-1)]--;
	for(int i=1;i<n;i++) a[i]+=a[i-1];
	while(q--)
	{
	    int x;cin>>x;
	    if(x>=a[n-1]) cout<<-1<<"\n";
	    else cout<<upper_bound(a,a+n,x)-a<<endl;
	}
	return 0;
}

T2

最简单的暴力做法肯定是非常容易想到的。而这个式子也很容易发现,是可以线段树优化。所以考虑线段数优化dp即可。

代码

点击查看代码
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f3f3f3f3f
#define int long long
#define endl '\n'
using namespace std;
const int maxn=5e5+5,maxm=1e17;
struct SGT
{
	int ls,rs;
	int x;
}tree[40*maxn];
int n,tot,rt;
int ans,l,r,lst;
int a[maxn];
void push_up(int x)
{
	tree[x].x=max(tree[tree[x].ls].x,tree[tree[x].rs].x);
}
void update(int &x,int l,int r,int p,int k)
{
	if(!x) x=++tot;
	if(l==r)
	{
		tree[x].x=max(tree[x].x,k);
		return ;
	}
	int mid=(l+r)/2;
	if(p<=mid) update(tree[x].ls,l,mid,p,k);
	else update(tree[x].rs,mid+1,r,p,k);
	push_up(x);
}
int query(int x,int l,int r,int L,int R)
{
	if(!x) return 0;
	if(L<=l&&r<=R) return tree[x].x;
	int mid=(l+r)/2, res=0;
	if(L<=mid) res=max(res,query(tree[x].ls,l,mid,L,R));
	if(R>mid) res=max(res,query(tree[x].rs,mid+1,r,L,R));
	return res;
}
signed main()
{
	freopen("sequence.in","r",stdin);
	freopen("sequence.out","w",stdout);
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	cin>>n>>l>>r;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
		lst=max(1ll,query(rt,1,maxm,l-a[i],r-a[i])+1);
		update(rt,1,maxm,a[i],lst);
		ans=max(ans,lst);
	}
	cout<<ans<<endl;
	return 0;
}

T3

排序之后做差分,你就会发现答案其实不是很大。

通过抽屉原理,可以证明得到当数字的总个数达到了一定程度之后,它的答案就会降到1。所以我们直接考虑暴力即可。

代码

点击查看代码
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f3f3f3f3f
#define int long long
#define endl '\n'
using namespace std;
const int maxn=2e5+5;
int p[1000005],n,g;
void dfs(int x,int y,int now,int g)
{
	if(x==n)
	{
		if(__gcd(g,p[x]+y-now)==1) cout<<y,exit(0);
		return ;
	}
	for(int i=0;i<=y-now;i++) dfs(x+1,y,now+i,__gcd(g,p[x]+i));
}
signed main()
{
	freopen("cookie.in","r",stdin); 
	freopen("cookie.out","w",stdout); 
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	cin>>n;
	for(int i=1;i<=n;i++) cin>>p[i],g=__gcd(g,p[i]);
	if(g==1)
	{
		cout<<0;
		return 0; 
	}
	if(n>23)
	{
		cout<<1;
		return 0;
	}
	for(int i=1;;i++) dfs(1,i,0,0);
	return 0;
}

T4

如果仅要求不少,那么这道题是好做的。

那其实你可以将每一个看作一个线段

然后再用map记录下来。

至于排序的过程,你会发现部分过程要存很多int。这里我们可以使用array

代码

点击查看代码
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f3f3f3f3f
#define int long long
#define endl '\n'
using namespace std;
const int maxn=2e5+5,mod=1e9+7;
void cal(int&x,int val)
{
	x=(x+val)%mod;
}
int n,k;
pair<int,int>a[maxn];
vector<array<int,3> >v;
signed main()
{
	freopen("light.in","r",stdin);
	freopen("light.out","w",stdout);
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i].first>>a[i].second;
	map<int,vector<int> >mp;
	vector<array<int,4> >v2;
	for(int i=1;i<=n;i++)
	{
		mp[a[i].first].push_back(a[i].second);
		v2.push_back({a[i].first,a[i].first-a[i].second,a[i].second,1});
	}
	for(int i=1;i<=n;i++)
	{
		v.push_back({a[i].first-a[i].second,a[i].first,1});
		v.push_back({a[i].first,a[i].first+a[i].second,1});
		v.push_back({a[i].first-a[i].second,a[i].first+a[i].second,-1});
	}
	for(auto now:mp)
	{
		int x=now.first;
		vector<int> vct=now.second;
		if(vct.size()>1)
		{
			if(vct[0]==vct[1])
				v.push_back({x-vct[0],x+vct[0],-1});
			else
			{
				int a=vct[0],b=vct[1];
				if(a>b) swap(a,b);
				v2.push_back({x-a,x-b,a+b,1});
			}
		}
	}
	map<int,int> mp2;
	sort(v.begin(),v.end());
	for(auto a:v)
	{
		int l=a[0],r=a[1],w=a[2];
		cal(mp2[r],(mp2[l]+1)*w);
	}
	int ans=0;
	for(auto now:mp2)
	{
		int x=now.first,c=now.second;
		cal(ans,c);
	}
	map<pair<int,int>,int> dp;
	sort(v2.begin(),v2.end());
	for(auto a:v2)
	{
		int x=a[0],y=a[1],d=a[2],w=a[3];
		cal(dp[{x+d,y+d}],(dp[{x,y}]+1)*w);
	}
	for(auto now:dp)
	{
		int x=now.second;
		cal(ans,-x);
	}
	cout<<(ans+mod)%mod;
	return 0;
}

posted @ 2026-09-03 22:43  Engle_Chen  阅读(24)  评论(0)    收藏  举报