新生赛及预选赛 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\) ,上述方法明显具有正确性,但是无法通过该题目。
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
*/
标签:10,int,void,re,while,wr,预选赛,赛及
From: https://www.cnblogs.com/Hanggoash/p/18449016