新生赛及预选赛 10

新生赛及预选赛 10

这个和昨天的不太一样,但只做了四道题,昨天有点小摆

A

还是很清晰的一个模拟题,预处理的时候判断一下,在询问的时候二分查找就可以了。

Code

#include<bits/stdc++.h>
using namespace std;
template<typename T>inline void re(T &x)
{
	x=0;int f=1;char c=getchar();
	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
	while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
	x*=f;
}
template<typename T>inline void wr(T x)
{
	if(x<0)putchar('-'),x=-x;
	if(x>9)wr(x/10);
	putchar(x%10^48);
}
const int N=2e5+10;
int n,q,x[N],v[N],in[N];
inline void pre()
{
	re(n);
	for(register int i=1;i<=n;++i)
		re(x[i]),re(v[i]);
	in[1]=1;
	int nowv=0;x[n+1]=2005120700;
	for(register int i=1;i<=n;++i)
	{
		nowv+=v[i]; 
		if(x[i]+nowv<x[i+1])
		{
			v[i]=nowv;
			break;	
		}
		in[i+1]=1;
		nowv-=(x[i+1]-x[i]);
		v[i]=x[i+1]-x[i];
	}
}
inline void solve(int k)
{
	int pos=upper_bound(x+1,x+n+1,k)-x-1;
	if(in[pos]&&x[pos]+v[pos]>=k)puts("Yes");
	else puts("No");
}
int main()
{
	pre();
	int k;
	re(q);
	while(q--)
	{
		re(k);
		solve(k);
	}
	return 0;
}

B

\(k\) 个数组 ,记从每个数组的 \(a[i]\) 个人中共选出 \(x\) 个人的方案数为 \(f(x)\) (不能全都不选,也就是 \(x>0\) )。

\(\sum_{x=1}^{p} f(x)\)

B 题就是这个题在 \(k=2\) 时候的简单版本,很明显直接人肉枚举情况就可以通过了。

Code

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int MOD=13331;
int n,m,p;
int C[1010][1010];
inline void pre()
{
	cin>>n>>m>>p;
	for(int i=0;i<=1000;++i)	
	{
		C[i][0]=1;
		for(int j=1;j<=i;++j)
			C[i][j]=(C[i-1][j]+C[i-1][j-1])%MOD;				
	}
}
inline void solve()
{
	int ans=0;
	for(int i=0;i<=min(n,p);++i)
		for(int j=0;j<=m&&(i+j<=p);++j)
			ans+=1ll*C[n][i]*C[m][j]%MOD,ans%=MOD;
	cout<<ans-1;
}
signed main()
{
	pre();
	solve();
	return 0;
}

C

C 题就是 B 题的原版描述,个人写了个 DP ,大概思路是:定义 \(dp[i][j]\) 为,前 \(i\) 个数组,选了 \(j\) 个人的方案数。

那么转移方程其实也很明显:

for(register int i=1;i<=n;++i)
{
    for(register int j=0;j<=p;++j)
    {
		for(register int x=0;x<=min(j,a[i]);++x)
        {
            dp[i][j]+=dp[i-1][j-x]*C(a[i],x);
		}
    }
}

但是可惜的是这道题的数据范围十分的大, \(k\le \sum a_i\le10^6\) ,上述方法明显具有正确性,但是无法通过该题目。

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
template<typename T>inline void re(T &x)
{
	x=0;int f=1;char c=getchar();
	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
	while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
	x*=f; 
} 
const int MOD=998244353;
inline int power(int a,int b)
{
	int ans=1;
	while(b)
	{
		if(b&1)ans=ans*a%MOD;
		a=a*a%MOD;
		b>>=1;
	}
	return ans%MOD;
}
int dp[3][1000010],now=1;
int k,a[100010],p;
int jc[1000010];
inline void pre()
{
	re(k);
	for(register int i=1;i<=k;++i)
		re(a[i]);
	re(p);		
	jc[0]=1;
	for(register int i=1;i<=p;++i)jc[i]=jc[i-1]*i%MOD;
}
inline int C(int x,int y)
{
	return jc[x]*power(jc[y]*jc[x-y]%MOD,MOD-2)%MOD;
}
void display(int i)
{
	printf("%lld:\n",i);
	for(register int j=0;j<=p;++j)
		printf("%lld ",dp[now][j]);
	putchar('\n');		
}
inline void solve()
{
	dp[0][0]=1;
	for(register int i=1;i<=k;++i,now^=1)
	{
		for(register int j=0;j<=p;++j)
		{		
			int s=0;
			for(register int x=0;x<=min(a[i],j);++x)
				s+=dp[now^1][j-x]*C(a[i],x)%MOD,s%=MOD;
			dp[now][j]=s;
		}
	}
	now^=1;
	int ans=0;
	for(register int i=1;i<=p;++i)ans+=dp[now][i],ans%=MOD;
	cout<<ans;
}
signed main()
{
	pre();
	solve();
	return 0;
}
//TLE

D

不会

E

给出若干个数字,已知这些数字是若干个未知数字的因数(可重),求出这若干个未知数字。

很明显的是我们从最大的数开始枚举,然后剔除它所有的因数,直到集合里再也没有数字即可。

这里用了个 multiset 实现,剔除操作是 wipe() 函数。

数据范围很小,随便怎么做应该都能过。

Code

#include<bits/stdc++.h>
using namespace std;
template<typename T>inline void re(T &x)
{
	x=0;int f=1;char c=getchar();
	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
	while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
	x*=f;
}
template<typename T>inline void wr(T x)
{
	if(x>9)wr(x/10);
	putchar(x%10^48);
 } 
multiset<int> s;
int n,a[100000];
int cnt,ans[100000];
inline void wipe(int x)
{
	int i;
	for(i=1;i*i<x;++i)
	{
		if(x%i!=0)continue;
		auto it=s.find(i);s.erase(it);
		it=s.find(x/i);s.erase(it);
	}
	if(i*i!=x)return;
	auto it=s.find(i);s.erase(it);
}
inline void pre()
{
	re(n);
	for(register int i=1;i<=n;++i)re(a[i]),s.insert(a[i]);
	while(s.size())
	{
		auto it=s.end();it--;
		ans[++cnt]=*it;
		wipe(*it);
	}
}
int main()
{
	pre();
	wr(cnt),putchar('\n');
	for(register int i=cnt;i>=1;--i)wr(ans[i]),putchar(' ');
	return 0;
 } 
 /*
12
1 2 1 6 3 5 1 2 3 4 6 12
 */
posted @ 2024-10-06 13:26  Hanggoash  阅读(14)  评论(0编辑  收藏  举报
动态线条
动态线条end