版权声明:欢迎评论交流,转载请注明原作者。 https://blog.csdn.net/m0_37809890/article/details/83375642
A. Birthday 计算
一共n种硬币,小萌已经有了k种硬币,小萌的m个朋友想每人送给小萌一些硬币,且满足以下条件,求每个人最少送几枚硬币。
- 每人送的个数相等且所有要送的硬币种类不同。
- 小萌最后收到的硬币至少包含L种她没有的。
计算题,求满足
ll ans = (k+l+m-1)/m;
printf("%I64d\n",ans*m>n?-1:ans );
B. LCM 计算
给定b(1e10),对于1<=a<=1e18,求lcm(a,b)/a的不同取值个数。
lcm(a,b)/a = a*b/gcd(a,b)/a = b/gcd(a,b),即求b的因数个数
ll b = read(), ans = 0, i;
for(i=1;i*i<b;++i)
if(b%i==0)
ans+=2;
if(i*i==b) ++ans;
printf("%I64d\n",ans );
C. Colored Rooks 构造
给定n(100)个点,m(1000)条边的无向连通图。在1e9*1e9的坐标平面上放置不超过5000个象棋中的车,每个车都归属于原图中的某个节点。要求:
- 每个节点至少有一个车。
- 每个节点的车集连通。(上下,左右,不会被阻挡)
- 两个节点的车集的并集连通 当且仅当 两个节点有边直接相连.
构造这样的坐标平面,输出每个节点辖制的车的数量及每个车的坐标。
坐标平面足够,点数足够(只有1000条边,可以放5000个棋子),把每个节点辖制的车都放在一行则自然连通。如果两个节点有边相连,那么就在很远的列给他们两行都放一个点。
set<int> ans[M];
int n=read(),m=read();
for(int i=1;i<=n;++i)
ans[i].insert(i);
for(int i=1;i<=m;++i)
{
int a = read(), b=read();
ans[a].insert(a*1000+b);
ans[b].insert(a*1000+b);
}
for(int i=1;i<=n;++i)
{
printf("%d\n",ans[i].size() );
for(auto x:ans[i])
printf("%d %d\n",i,x );
}
D. Array Without Local Maximums 求方案数,dp
长度为n(1e5)的数组,值域为1到200,且每个数的旁边必有一个大于等于它的数。有些数字被擦掉了,问共有几种填充的方案满足上述要求。
遇事不决写暴力,搜索不行就DP
大DP
- 状态表示:
- 状态边界:
- 状态转移:当第pos位不为-1时,
表示这一位无须填充,直接转移即可。
否则
我有一个绝妙的递归算法,但是栈空间太小,写不下。
改成递推,添加前缀和数组。
/* LittleFall : Hello! */
//#pragma comment(linker, "/STACK:102400000,102400000")
#include <bits/stdc++.h>
using namespace std; using ll = long long; inline int read();
const int M = 100016, MOD = 998244353;
int save[M];
ll dp[M][201][2], sum[2][201][2];
//dp[i][j][k]表示需要确定前i位,第i+1位为j,第i+2位是否大于等于第i+1位时的方案数.
int solve(int n)
{
for(int nxt=1;nxt<=200;++nxt)
{
dp[0][nxt][1] = 1;
sum[1][nxt][1] = sum[1][nxt-1][1] + 1;
}
for(int pos=1;pos<=n;++pos)
{
memcpy(sum[0],sum[1],sizeof(sum[1]));
memset(sum[1],0,sizeof(sum[1]));
for(int nxt = 1;nxt<=200;++nxt)
{
for(int tag=0;tag<=1;++tag)
{
if(save[pos]!=-1)
{
if(tag==0 && save[pos]<nxt)
dp[pos][nxt][tag] = 0;
else
dp[pos][nxt][tag] = dp[pos-1][save[pos]][nxt>=save[pos]];
}
else
{
dp[pos][nxt][tag] += sum[0][nxt][1] - sum[0][tag ? 0 : nxt-1][1];
dp[pos][nxt][tag] += sum[0][200][0] - sum[0][nxt][0];
}
dp[pos][nxt][tag] %= MOD;
sum[1][nxt][tag] = sum[1][nxt-1][tag] + dp[pos][nxt][tag];
}
}
}
return dp[n][1][1];
}
int main(void)
{
int n = read();
for(int i=1;i<=n;++i)
save[i] = read();
printf("%d\n",solve(n) );
return 0;
}