列表

详情


NC207574. SumoandGroupActivity

描述

Sumo是一个社交达人,他经常辗转各地开展party。

将社区想象为一个坐标轴,给定许多个可以开展party的坐标点,以及Sumo的家的坐标点。Sumo接下来要开展m次party,因此还需要选择m个地点。

Sumo希望知道有多少种选取地点的方案,使得这些方案满足以下条件:
请告诉Sumo有多少种选取party地点的方案,答案可能过大,请输出答案对取模后的结果。

两种方案(k_1,k_2,k_3...k_m)(p_1,p_2,p_3...p_m),若存在,则认为两个方案是不同的。

输入描述

输入的第一行包含四个空格分隔的整数
n表示有n个备选地点,a表示Sumo最近一次开party的地点序号,b表示Sumo家的地点序号,m表示还要举办party的次数。
接下来一行有n个数,其中x_i代表序号为i的地点的坐标,保证坐标两两不同。(两个地点之间的距离即为坐标之差)

输出描述

由于答案可能过大,因此只需要输出一个整数,表示总数对取模后的结果。

示例1

输入:

5 4 3 1
25 18 20 13 7

输出:

2

示例2

输入:

5 2 4 2
7 13 18 20 25

输出:

2

示例3

输入:

5 3 4 1
7 13 18 20 25

输出:

0

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 898ms, 内存消耗: 98532K, 提交时间: 2020-06-15 23:09:11

#include <bits/stdc++.h>
#define mp make_pair
#define pb push_back
#define sz(x) (int)x.size()
#define all(x) begin(x), end(x)
#define fi first
#define se second
#define debug(x) cerr << #x << " " << x << '\n'
using namespace std;
using ll = long long;
using pii = pair<int,int>;
using pli = pair<ll,int>;
const int INF = 0x3f3f3f3f, N = 5e3 + 5;
const ll LINF = 1e18 + 5;
constexpr int mod = 1e9 + 7;
int n, m, a, b, aa, bb;
int x[N];
pii tmpx[N];
int dp[N][N], sum[N];
void add(int &x, int y) { x += y; if(x>=mod) x -= mod; }
int Add(int x, int y) { x += y; return (x>=mod ? x-mod : x); }
int Sub(int x, int y) { x -= y; return (x<0 ? x+mod : x); }
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	cin >> n >> aa >> bb >> m;
	for(int i=1; i<=n; i++) 
	{
		cin >> x[i];
		tmpx[i] = {x[i], i};
	}
	sort(x+1, x+n+1);
	sort(tmpx+1, tmpx+n+1);
	for(int i=1; i<=n; i++)
	{
		if(tmpx[i].se==aa) a = i;
		if(tmpx[i].se==bb) b = i;
	}
	dp[0][a] = 1;
	for(int i=1; i<=m; i++)
	{
		for(int j=1; j<=n; j++) sum[j] = Add(sum[j-1], dp[i-1][j]);
		for(int j=1; j<=n; j++)
		{
			if(j==b) continue;
			if(j<b) 
			{
				add(dp[i][j], sum[j-1]);
				int p = upper_bound(x+j, x+b+1, (x[j]+x[b]+1)/2-1) - x - 1;
				add(dp[i][j], Sub(sum[p], sum[j]));
			}
			else
			{
				add(dp[i][j], Sub(sum[n], sum[j]));
				int p = upper_bound(x+b, x+j+1, (x[j]+x[b])/2+1) - x - 1;
				add(dp[i][j], Sub(sum[j-1], sum[p-1]));
			}
		}
	}
	int ans = 0;
	for(int i=1; i<=n; i++) add(ans, dp[m][i]);
	cout << ans;
	return 0;
}

C++11(clang++ 3.9) 解法, 执行用时: 405ms, 内存消耗: 196600K, 提交时间: 2020-06-07 09:50:03

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAX_N=5010;
const long long MOD=1e9+7;
long long dp[MAX_N][MAX_N];
long long sum[MAX_N];
int p[MAX_N];
int lx[MAX_N],ux[MAX_N];
int main(void){
	int n,a,b,m,i,j;
	scanf("%d%d%d%d",&n,&a,&b,&m);
	for(i=1;i<=n;i++)
	scanf("%d",&p[i]);
	a=p[a];b=p[b];
	sort(p+1,p+n+1);
	a=lower_bound(p+1,p+n+1,a)-p;
	b=lower_bound(p+1,p+n+1,b)-p;
	for(i=1;i<=n;i++){
		if(i==a)
		sum[i]=sum[i-1]+1;
		else
		sum[i]=sum[i-1];
	}
	dp[0][a]=1;
	for(j=1;j<=n;j++){
		lx[j]=lower_bound(p+1,p+n+1,(p[b]+p[j]+1)/2)-p-1;
		ux[j]=upper_bound(p+1,p+n+1,(p[b]+p[j])/2)-p;;
	}
	for(i=1;i<=m;i++){
		for(j=1;j<=n;j++){
			if(p[j]<p[b]){
				//int x=lower_bound(p+1,p+n+1,(p[b]+p[j]+1)/2)-p-1;
				int x=lx[j];
				dp[i][j]=(sum[x]-dp[i-1][j]+MOD)%MOD;
			}
			else if(p[j]>p[b]){
				//int x=upper_bound(p+1,p+n+1,(p[b]+p[j])/2)-p;
				int x=ux[j];
				dp[i][j]=((sum[n]-sum[x-1]+MOD)%MOD-dp[i-1][j]+MOD)%MOD;
			}
		}
		for(j=1;j<=n;j++)
		sum[j]=(sum[j-1]+dp[i][j])%MOD;
	}
	long long ans=0;
	for(j=1;j<=n;j++){
		//cout<<j<<" "<<dp[m][j]<<"\n"; 
		ans=(ans+dp[m][j])%MOD;
	}
	printf("%lld\n",ans);
	return 0;
}

上一题