题面(加密)

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

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. 【LeetCode 37】解数独

    题目链接 [题解] 回溯法搞一下. 用set和数组下标判重. [代码] class Solution { public: set<int> myset[9]; int hang[9][10 ...

  2. Jetson Nano 系列教程2:串口调试接口登录Jetson Nano

    连接Jetson Nano可以有多种方法,这里我们一一介绍一下.开始本章节前,请先参考上一章,烧写好镜像 直接连接 所谓直接连接,就是将Jetson Nano当做主机,连接HDMI屏幕,连接键盘和鼠标 ...

  3. UML的类型

    分类 UML从考虑系统的不同角度出发,定义了用例图.类图.对象图.包图.状态图.活动图.序列图.协作图.构件图.部署图等10种图. 常见的UML图有用例图(Use Case Diagram).类图(C ...

  4. 73、salesforce通过JAVA来Call在salesforce中已经写好的Restful处理接口

    /** *使用salesforce通过REST方式作为webservice,需要以下几点 *1.类和方法需要global,方法需要静态 *2.类需要通过RestResource(UrlMapping= ...

  5. 《Java技术》 第二次作业

    java第二次作业 (一)学习总结 1.学习使用Eclipse关联jdk源代码,查看String类的equals()方法,截图,并学习其实现方法.举例说明equals方法和==的区别. 在Eclips ...

  6. linux(Ubuntu) 搭建LAMP环境

    1.更新源 sudo apt- get update 2.安装常用软件 SSH.Vim.Git.Tree ①SSH sudo apt-get install openssh-server 管理命令:s ...

  7. redis zset 介绍

    $key = 'key'; //新增 zadd($key,分数,标识) //删除某个标识 zrem($key,标识) //查询某个标识的排名(从0开始的 所有在输出的时候要加一) zrevrank($ ...

  8. QT5.2 Assistant-设置应用程序图标

       在Qt助手(assistant.exe)搜索关键字"Setting the Application Icon"就可以看到在各种平台设置Qt程序图标的方法,包括QT支持的Win ...

  9. JavaScript 学习笔记(初学者)

    Java Script 基础 一. JS的简介     JavaScript是一种网页编程技术,经常用于创建动态交互网页     JavaScript是一种基于对象和事件驱动的解释性脚本语言,类似C语 ...

  10. 响应式web开发的一些文章

    CSS Device Adaptation:关注 W3C 建议的 CSS 设备适配标准. “在 CSS 中使用 LESS 实现更多的功能”(作者:Uche Ogbuji,developerWorks, ...