题面(加密)

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

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. ZROI week3

    作业 poj 1091 跳蚤 容斥原理. 考虑能否跳到旁边就是卡牌的\(gcd\)是否是1,可以根据裴蜀定理证明. 考虑正着做十分的麻烦,所以倒着做,也就是用\(M^N - (不合法)\)即可. 不合 ...

  2. 【缓存与性能优化】方法论:如何优化一个Web系统的性能

    1.性能简介 一个网络请求的等待: 减少等待时间方式 不同位置对性能的操控 开发人员优化性能的方式 性能指标 2.缓存 缓存是把一些需要计算或者访问数据库的数据,放到内存中,当客户端访问时,直接从内存 ...

  3. CJE-Jenkins认证工程师考试预约报名流程

    先决条件 考试费用150美元,需要由master/visr信用卡支付 考试全英文  哈哈哈 考试目的 通过各种渠道能够找到Jenkins的学习资料,并能够完成jenkins的配置管理,还是想全面的系统 ...

  4. 用 Flask 来写个轻博客 (7) — (M)VC_models 的关系(many to many)

    目录 目录 前文列表 扩展阅读 前期准备 多对多 使用样例 一直在使用的 session 前文列表 用 Flask 来写个轻博客 (1) - 创建项目 用 Flask 来写个轻博客 (2) - Hel ...

  5. spss乱码问题解决

    spss乱码问题解决 方法1:网友kuangsir6提供 选择字体为:DFKai-SB 格式(我并没有找到这个格式) 方法是 SPSS(PASW)---Edit---Options---Viewer- ...

  6. 大数据学习笔记之Hadoop(一):Hadoop入门

    文章目录 大数据概论 一.大数据概念 二.大数据的特点 三.大数据能干啥? 四.大数据发展前景 五.企业数据部的业务流程分析 六.企业数据部的一般组织结构 Hadoop(入门) 一 从Hadoop框架 ...

  7. ubuntu安装完成后需要做的事情

    1.删除libreoffice libreoffice虽然是开源的,但是Java写出来的office执行效率实在不敢恭维,装完系统后果断删掉 [html] view plain copy sudo a ...

  8. linux基础--目录介绍

    Windows和Linux文件系统区别 在 windows 平台下,打开“计算机”,我们看到的是一个个的驱动器盘符: 每个驱动器都有自己的根目录结构,这样形成了多个树并列的情形,如图所示: 在 Lin ...

  9. CookieUtil.java

    package util; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.n ...

  10. Mysq sql语句教程

    mysql管理命令  show  databases;  显示服务器上当前所有的数据库  use  数据库名称;  进入指定的数据库  show  tables;  显示当前数据库中所有的数据表  d ...