题面(加密)

不得不说这次的题除了引起单身汪极度不适之外还是出的很有水平的……

A.

很好的dp题

模型非常简单,如果数据范围足够友好的话就是一道dp入门题

30%:

我们可以设$dp[i][j]$为到第i天一共喂食给出了j块饼干的方案数

易得转移方程:$dp[i][j+k]=\sum \limits_{k=0}^{min(m-1,n-j)}{dp[i-1][j]}$,i枚举天数,j枚举已给出数量,k枚举下一步给出数量

$\sum \limits_{i=1}^{n}{dp[i][n]}$即为答案

但是i是要枚举到d的,我们的二维数组显然开不了这么大,所以我们可以得到30分的好成绩(滑稽

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
typedef long long ll;
const int N=;
const ll mod=;
int n,m;
ll dp[N][N],D;
void work()
{
if(1LL*n>=1LL*m*D||m<=)
{
puts("");
return ;
}
memset(dp,,sizeof(dp));
for(int i=;i<=min(m-,n);i++)
dp[][i]=;
for(int i=;i<=D;i++)
for(int j=;j<min(1LL*n,D*m);j++)
for(int k=;k<=min(m-,n-j);k++)
(dp[i][j+k]+=dp[i-][j])%=mod;
ll ans=;
for(int i=;i<=D;i++)
(ans+=dp[i][n])%=mod;
cout<<ans%mod<<endl;
}
int main()
{
while()
{
scanf("%d%lld%d",&n,&D,&m);
if(n==&&D==&&m==)break;
work();
}
return ;
}

(另外,冲着30分去就按着30分范围打,不要梦想把数组开到极限还能多得分……事实上博主的30分就因为数组开太大 炸了内存 没了)

100%:

d的范围十分大,但我们不难发现真正给出饼干的天数最多只有n

所以可以把上面那个状态数组的定义稍作更改:真正给出饼干天数为i,给出饼干数量为j时的方案数

另外,为了进一步优化复杂度,使用前缀和优化,我们需要对枚举变量的意义作改动,让等号左侧为$dp[i][j]$

$dp[i][j]=\sum \limits_{k=j-m+1}^{j-1}{dp[i-1][k]}$

在统计结果时,对于每个$dp[i][n]$,是从d天中选任意i天给出饼干,所以还要乘上相应组合数

即:$ans=\sum {dp[i][n]*C_d^i}$

组合数直接根据相邻两项关系递推算即可 记得不能直接除 要乘逆元

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int N=;
typedef long long ll;
const ll mod=;
ll dp[N][N],n,d,m,fac[N],C[N],sum[N];
ll qpow(ll a,ll b)
{
ll res=;
while(b)
{
if(b&)res=res*a%mod;
a=a*a%mod;
b>>=;
}
//if(res<0)cout<<"Jackpot!"<<endl;
return res;
}
ll inv(ll x)
{
return qpow(x,mod-);
}
void work()
{
if(n>=m*d||m<=)
{
puts("");
return ;
}
memset(dp,,sizeof(dp));
memset(sum,,sizeof(sum));
C[]=;
for(int i=;i<=min(n,d);i++)
{
C[i]=(C[i-]*(1LL*(d-i+)%mod))%mod*inv(i)%mod;
/* if(C[i]<0)while(1);
cout<<"***"<<C[i]<<endl;*/
}
for(int i=;i<m;i++)
dp[][i]=,(sum[i]=sum[i-]+dp[][i])%=mod;
for(int i=m;i<=n;i++)
sum[i]=sum[i-];
for(int i=;i<=n;i++)
{
for(int j=;j<=n;j++)
dp[i][j]=(sum[j-]-sum[max(0LL,j-m)]+mod)%mod;
// sum[0]=0;
for(int j=;j<=n;j++)
(sum[j]=sum[j-]+dp[i][j])%=mod;
} ll ans=;
for(int i=;i<=min(d,n);i++)
(ans+=dp[i][n]*C[i]%mod)%=mod;
cout<<ans<<endl; }
int main()
{
while()
{
scanf("%lld%lld%lld",&n,&d,&m);
if(!n&&!d&&!m)break;
work();
}
return ;
}

B.

数据很水,水到直接把这道题变成了最短路的板子……

枚举与1节点相连的点,对于每个点,把1和他们之间的边临时断开后跑最短路

用$dis[1]+len[i]$更新ans即可

正解似乎是什么二进制分组blablabla  我也不会啊

#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
#define pa pair<int,int>
using namespace std;
const int N=,M=;
int n,m,T;
int to[M<<],dis[N],vis[N],nxt[M<<],tot,head[N],del[M<<],len[M<<];
int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<='')x=x*+ch-'',ch=getchar();
return x*f;
}
void add(int x,int y,int z)
{
to[++tot]=y;
len[tot]=z;
nxt[tot]=head[x];
head[x]=tot;
}
void dj(int s)
{
memset(dis,0x3f,sizeof(dis));
memset(vis,,sizeof(vis));
priority_queue<pa> q;
dis[s]=;//vis[s]=1;
q.push(make_pair(,s));
while(!q.empty())
{
int x=q.top().second;
q.pop();
if(vis[x])continue;
vis[x]=;
for(int i=head[x];i;i=nxt[i])
{
if(del[i])continue;
int y=to[i];
if(dis[y]>dis[x]+len[i])
{
dis[y]=dis[x]+len[i];
q.push(make_pair(-dis[y],y));
}
}
}
/*for(int i=1;i<=n;i++)
cout<<dis[i]<<' ';
puts(" ");*/
}
void ini()
{
for(int i=;i<=n;i++)head[i]=;
for(int i=;i<=m*;i++)to[i]=nxt[i]=del[i]=len[i]=;
tot=;
}
void work()
{
n=read();m=read();
ini();
for(int i=;i<=m;i++)
{
int x=read(),y=read(),z=read();
add(x,y,z);add(y,x,z);
}
int ans=0x3f3f3f3f;;
for(int i=head[];i;i=nxt[i])
{
int y=to[i];
del[i]=del[i^]=;
dj(y);
del[i]=del[i^]=;
ans=min(ans,dis[]+len[i]);
}
cout<<(ans==0x3f3f3f3f?-:ans)<<endl;
return ;
}
int main()
{
T=read();
while(T--)work();
return ;
}

(如果要使用$i\ xor\ 1$查询反边这种操作的话,链式前向星的tot初值要设成1!!!一时nc又少30!!)

C.

鬼能想到正解的神题……

首先我们考虑对这个模型进行转化。我们把2n个数字看作节点,把每张卡牌看作
是连接两个点的有向边。
于是我们的问题可以等价转化为这一问题:把图中的某些边反向使得任何一个节点
至多被一条边指向。
我们很容易想到整张图可能会被分为若干个联通块。
首先我们考虑联通块构成了树的情况。我们发现我们可以直接dp
然后我们考虑联通块构成了基环外向树的情况。我们发现只要确定环上的边的指向,
后面的外向树部分的指向就可以确定了。对于环上面的指向问题,我们发现一共只有两种
指向的可能,枚举即可。
随后我们考虑更复杂的情况,n个点,n+1条边的情况,因为我们知道每一条边肯定
会至少指向一个点,所以由抽屉原理可以一定存在一个点被指向多次,所以一定不可行。
所以,我们可以发现我们需要处理的即一个基环外向树和树的森林。
而联通块之间互不影响,分别处理即可。

树的情况需要换根进行dp。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=;
const ll mod=;
int T,n,to[N<<],nxt[N<<],head[N],tot=;
int vis[N],v[N],f[N],g[N],edge,node;
int cire,pos,poss;
vector<int> sor;
int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<='')x=x*+ch-'',ch=getchar();
return x*f;
}
void add(int x,int y)
{
to[++tot]=y;
nxt[tot]=head[x];
head[x]=tot;
}
void dfs(int x)
{
vis[x]=;node++;
for(int i=head[x];i;i=nxt[i])
{
edge++;
if(vis[to[i]])continue;
dfs(to[i]);
}
}
void dp1(int x,int fa)
{
v[x]=;
for(int i=head[x];i;i=nxt[i])
{
if(to[i]==fa)continue;
if(!v[to[i]])
{
dp1(to[i],x);
f[x]+=f[to[i]]+(i&);
}
else pos=x,poss=to[i],cire=i;
}
}
void dp2(int x,int fa)
{
sor.push_back(g[x]);
for(int i=head[x];i;i=nxt[i])
{
if(to[i]==fa)continue;
if(i==cire||i==(cire^))
continue;
int contr=((i&)?-:);
g[to[i]]=g[x]+contr;
dp2(to[i],x);
}
}
void ini()
{
for(int i=;i<=n*;i++)
vis[i]=v[i]=f[i]=g[i]=head[i]=;
for(int i=;i<=n*;i++)
nxt[i]=to[i]=;
tot=;edge=node=;
}
void work()
{
n=read();ini();
for(int i=;i<=n;i++)
{
int x=read(),y=read();
add(y,x);add(x,y);
}
/*for(int i=2;i<=tot;i++)
cout<<'!'<<to[i]<<' '<<nxt[i]<<' '<<endl;*/
for(int i=;i<=n;i++)
if(!vis[i])
{
node=edge=;
dfs(i);
if((edge>>)>node)
{
puts("-1 -1");
return ;
}
}
int ans1=,num=;ll ans2=;
for(int i=;i<=(n<<);i++)
{
if(v[i])continue;
sor.clear();
num=cire=pos=poss=;
dp1(i,);g[i]=f[i];
dp2(i,);
if(!cire)
{
sort(sor.begin(),sor.end());//puts("QAQ");
for(int j=;j<sor.size();j++)
{
//cout<<'!'<<sor[j]<<endl;
if(sor[j]!=sor[])break;
num++;
}
ans1+=sor[];//cout<<"***"<<ans1<<endl;
}
else
{
cire=(cire&);//puts("QwQ");
if(g[pos]+(cire^)==g[poss]+cire)num=;
else num=;
ans1+=min(g[pos]+(cire^),g[poss]+cire);//cout<<"###"<<ans1<<endl;
}
(ans2*=1LL*num%mod)%=mod;
}
/*puts("---"); for(int i=1;i<=n*2;i++)
cout<<f[i]<<' '<<g[i]<<endl;puts("---");*/
cout<<ans1<<' '<<ans2<<endl;
}
int main()
{
T=read();
while(T--)work();
return ;
}

[7.19NOIP模拟测试6]失恋三连(雾 题解的更多相关文章

  1. 【3.16高一(第二学期)模拟测试】 T3,T4题解

    看到这个标题我想你一定会想为什么小编只发T3,T4的题解,原因有很多:1)小编也不怎么会讲:2)小编搜遍各大OJ,都没有找到可以提交的地方:3)虽然给了测试数据,小编懒得一个一个试.如果你找到了测评网 ...

  2. [NOIP模拟测试10]辣鸡(ljh) 题解

    首先计算块内贡献,很显然是$(x_2-x_1)*(y_2-y_1)*2$. 然后考虑矩形之间的贡献,sort一遍分类讨论$n^2$暴力即可. 注意考虑边界情况是否能多两个,以及角对角的情况. 另外,排 ...

  3. [7.22NOIP模拟测试7]方程的解 题解(扩展欧几里得)

    Orz 送分比较慷慨的一道题,疯狂特判能拿不少分. 对于$a>0,b>0$的情况: 用exgcd求出方程通解,然后通过操作得到最小正整数解和最大正整数解 他们以及他们之间的解满足等差数列性 ...

  4. csp-s模拟测试52平均数,序列题解

    题面:https://www.cnblogs.com/Juve/articles/11602244.html 平均数: 第k个平均数不好求,我们考虑二分,转化成平均数小于x的有几个 虑把序列中的每个数 ...

  5. 2019.8.3 [HZOI]NOIP模拟测试12 C. 分组

    2019.8.3 [HZOI]NOIP模拟测试12 C. 分组 全场比赛题解:https://pan.baidu.com/s/1eSAMuXk 刚看这题觉得很难,于是数据点分治 k只有1和2两种,分别 ...

  6. Android单元测试与模拟测试详解

    测试与基本规范 为什么需要测试? 为了稳定性,能够明确的了解是否正确的完成开发. 更加易于维护,能够在修改代码后保证功能不被破坏. 集成一些工具,规范开发规范,使得代码更加稳定( 如通过 phabri ...

  7. [开源]微信在线信息模拟测试工具(基于Senparc.Weixin.MP开发)

    目前为止似乎还没有看到过Web版的普通消息测试工具(除了官方针对高级接口的),现有的一些桌面版的几个测试工具也都是使用XML直接请求,非常不友好,我们来尝试做一个“面向对象”操作的测试工具. 测试工具 ...

  8. 安装nginx python uwsgi环境 以及模拟测试

    uwsgi帮助文档: http://uwsgi-docs-cn.readthedocs.io/zh_CN/latest/WSGIquickstart.html http://uwsgi-docs.re ...

  9. 利用Python中的mock库对Python代码进行模拟测试

    这篇文章主要介绍了利用Python中的mock库对Python代码进行模拟测试,mock库自从Python3.3依赖成为了Python的内置库,本文也等于介绍了该库的用法,需要的朋友可以参考下     ...

随机推荐

  1. nucleus plus学习总结

    前言:     最近一直都在看nucleus plus,之前看过一些linux内核的一些东西,但都是停留在文字上,代码看的很少,这个nucleus plus内核的代码量不大,看过source code ...

  2. PLSQL连接虚拟机中的Oracle数据库

    下面这个连接对以后虚拟机安装非常有用!!! https://blog.csdn.net/lixin5456985/article/details/81670095

  3. AcWing 217. 绿豆蛙的归宿 (概率期望+拓扑排序)打卡

    给出一个有向无环的连通图,起点为1,终点为N,每条边都有一个长度. 数据保证从起点出发能够到达图中所有的点,图中所有的点也都能够到达终点. 绿豆蛙从起点出发,走向终点. 到达每一个顶点时,如果有K条离 ...

  4. 使用 nuxt+iview-admin+koa2 开发项目

    公司最近在做的一个项目,依然是采用熟悉的vue开发,数据平台因为其数据量大的特点,采用传统的spa模式,首页加载时间很长,而SSR这种方式对于首屏的加载时间优化显而易见,同时还可以方便的进行SEO.因 ...

  5. layui点击图片放大-多图显示

    layui点击图片放大-多图显示 标签(空格分隔): js HTML // div <div id="photo-list"> <img class=" ...

  6. Linux(一)—— Linux环境搭建

    Linux环境搭建 一.虚拟机安装 1.下载地址 https://my.vmware.com/web/vmware/info/slug/desktop_end_user_computing/vmwar ...

  7. 如何更规范化的编写JAVA 代码

    如何更规范的编写JAVA代码 一.MyBatis 不要为了多个查询条件而写 1 = 1 当遇到多个查询条件,使用where 1=1 可以很方便的解决我们的问题,但是这样很可能会造成非常大的性能损失, ...

  8. 洛谷 P2023 维护序列——线段树

    先上一波题目 https://www.luogu.org/problem/P2023 复习了一波线段树 题目涉及的操作有区间加 区间乘以及区间求和 tips:线段树在传标记的时候 优先传乘法标记再传加 ...

  9. libvirt虚拟机管理常用指令

    创建虚拟机 virt-install virt-install --connect qemu:///system -n $NAME -r $MEM -f $DISK -s $DISK_SIZE --v ...

  10. 在已有QT项目中添加多个UI布局界面

    1.在工程中右键->添加新文件,按图选择 2.选择窗口部件 3.创建UI控制类 注意上图红框中命名按实际需要定义,否则后期改动要修改UI文件参数 4.修改UI文件,框1是窗口部件父类,框2是UI ...