题目名称 笔记 括号 城堡
可执行文件名 note brackets castle
输入文件名 note.in brackets.in castle.in
输出文件名 note.in brackets.out castle.in
每个测试点时限 1 秒 1 秒 1 秒
内存限制 512MB 512MB 512MB
测试点数目 20 20 10
每个测试点分值 5 5 10
是否有部分分 否 否 否
题目类型 传统型 传统型 传统型
测试题 #4 笔记
笔记
【问题描述】
给定一个长度为?的序列?,下标编号为1~?。序列的每个元素都是1~?的
整数。定义序列的代价为
? ?+1 − ? ?
?−1
?=1
你现在可以选择两个数?和?,并将序列?中所有的?改成?。?可以与?相等。
请求出序列最小可能的代价。
【输入格式】
输入第一行包含两个整数?和?。第二行包含?个空格分隔的整数,代表序
列?。
【输出格式】
输出一行,包含一个整数,代表序列最小的代价。
【样例输入 1】
4 6
1 2 3 4 3 2
【样例输出 1】
3
【样例输入 2】
10 5
9 4 3 8 8
【样例输出 1】
6
【样例解释】
样例 1 中,最优策略为将 4 改成 3。样例 2 中,最优策略为将 9 改成 4。
测试题 #4 笔记
【数据规模和约定】
31。
60%的数据,?,? ≤ 2000。
对于100%的数据,1 ≤ ?,? ≤ 100,000。

/*暴力+小小的优化(没有啥大用)*/
#include<cstdio>
#include<ctime>
#include<algorithm>
#define maxn 100010
using namespace std;
int n,m,a[maxn],b[maxn],c[maxn],ans;
int init(){
int x=,f=;char s=getchar();
while(s<''||s>''){if(s=='-')f=-;s=getchar();}
while(s>=''&&s<=''){x=x*+s-'';s=getchar();}
return x*f;
}
int Abs(int x){
return x<?-x:x;
}
int main()
{
freopen("note.in","r",stdin);
freopen("note.out","w",stdout);
n=init();m=init();
for(int i=;i<=m;i++)
a[i]=init();
if(n<=){
for(int i=;i<m;i++)
if((a[i]<a[i-]&&a[i]<a[i+])||(a[i]>a[i-]&&a[i]>a[i+]))
c[++c[]]=a[i];
c[++c[]]=a[];c[++c[]]=a[m];
}
else for(int i=;i<=n;i++)c[++c[]]=a[i];
sort(c+,c++c[]);
c[]=unique(c+,c++c[])-c-;
for(int i=;i<m;i++)
ans=ans+Abs(a[i+]-a[i]);
for(int i=;i<=c[];i++)
for(int j=;j<=n;j++){
for(int k=;k<=m;k++)
if(a[k]==c[i])b[k]=j;
else b[k]=a[k];
long long mx=;
for(int k=;k<m;k++){
mx=mx+Abs(b[k+]-b[k]);
if(ans<mx)break;
}
if(ans>mx)ans=mx;
//if(clock()>950){
// printf("%lld\n",ans);return 0;
//}
}
printf("%lld\n",ans);
fclose(stdin);fclose(stdout);
return ;
}
/*
嗯很好的思路 每个数字只与两边的有关
假设我们尝试着改 x 改成什么玩意是可以直接算出来的
先预处理处所有与x相邻的数们 那每个都要与x做差然后绝对值
如果我们队这一坨数排序的话 那么显然x改成中位数最优
然后枚举一下x 比较一下就好了
每个x都要sort一遍 这个并不会很慢 均摊还是很快的
*/
#include<cstdio>
#include<vector>
#include<algorithm>
#define maxn 100010
#define ll long long
using namespace std;
ll n,m,a[maxn],b[maxn];
ll sta,mx;
vector<ll>G[maxn];
ll init(){
ll x=,f=;char s=getchar();
while(s<''||s>''){if(s=='-')f=-;s=getchar();}
while(s>=''&&s<=''){x=x*+s-'';s=getchar();}
return x*f;
}
ll Abs(ll x){
return x<?-x:x;
}
int main(){
freopen("note.in","r",stdin);
freopen("note.out","w",stdout);
n=init();m=init();
for(ll i=;i<=m;i++)a[i]=init();
for(ll i=;i<=m;i++)
if(a[i]!=a[i-])b[++b[]]=a[i];
for(ll i=;i<m;i++)sta+=Abs(a[i+]-a[i]);
m=b[];b[]=;
for(ll i=;i<m;i++){
G[b[i]].push_back(b[i-]);
G[b[i]].push_back(b[i+]);
}
if(b[])G[b[]].push_back(b[]);
if(b[m-])G[b[m]].push_back(b[m-]);
for(ll i=;i<=n;i++){
ll len=G[i].size();
if(!len)continue;
sort(G[i].begin(),G[i].end());
ll mid=G[i][(len+)/-];
ll pre=,now=;
for(ll k=;k<len;k++){
pre+=Abs(G[i][k]-i);
now+=Abs(G[i][k]-mid);
}
mx=max(mx,pre-now);
}
printf("%I64d\n",sta-mx);
return ;
}

测试题 #4 括号
括号
【问题描述】
有一个长度为?的括号序列,以及?种不同的括号。序列的每个位置上是哪
种括号是随机的,并且已知每个位置上出现每种左右括号的概率。求整个序列是
一个合法的括号序列的概率。
我们如下定义合法括号序列:
 空序列是合法括号序列;
 如果?是合法括号序列,那么???是合法括号序列,当且仅当?和?是同种
的左右括号;
 如果?和?是合法括号序列,那么??是合法括号序列。
【输入格式】
输入第一行包含两个整数?和?。接下来的输入分为?组,每组?行。第?组第
?行包含两个实数?[?,?]和?[?,?],分别代表第?个位置上是第?类的左括号和右括号
的概率。
【输出格式】
输出一行,包含一个实数,代表序列是合法括号序列的概率。建议保留至少
5 位小数输出。只有当你的输出与标准答案之间的绝对误差不超过10 −5 时,才会
被判为正确。
【样例输入 1】
2 1
1.00000 0.00000
0.00000 1.00000
【样例输出 1】
1.00000
【样例输入 2】
4 1
0.50000 0.50000
1.00000 0.00000
0.00000 1.00000
0.50000 0.50000
测试题 #4 括号
【样例输出 2】
0.25000
【数据规模和约定】
对于20%的数据,? ≤ 50,? = 1,所有位置的概率非 0 即 1。
另外有 30%的数据,? ≤ 34,? = 1,前 10 个和后 10 个位置的所有概率都
是 0.5,中间剩余位置的概率非 0 即 1。
80%的数据,?,? ≤ 50。
对于100%的数据,1 ≤ ? ≤ 200,1 ≤ ? ≤ 50。

/*dpwa成了傻逼 还是交的暴力*/
#include<iostream>
#include<cstdio>
#define maxn 210
#define ld long double
using namespace std;
int n,k,s[maxn];
ld g[maxn][maxn][],ans;
void Dfs(int now,ld x){
if(now==n+){
int falg=;
for(int i=;i<=k;i++)
if(s[i]){
falg=;break;
}
if(falg)ans+=x;return;
}
for(int i=;i<=k;i++){
if(s[i]->=&&g[now][i][]){
s[i]--;Dfs(now+,x*g[now][i][]);s[i]++;
}
if(s[i]+<=n-now&&g[now][i][]){
s[i]++;Dfs(now+,x*g[now][i][]);s[i]--;
} }
}
int main()
{
freopen("brackets.in","r",stdin);
freopen("brackets.out","w",stdout);
cin>>n>>k;
for(int i=;i<=n;i++)
for(int j=;j<=k;j++)
cin>>g[i][j][]>>g[i][j][];
if(n&){
printf("0.00000\n");return ;
}
Dfs(,);printf("%.5lf",double(ans));
fclose(stdin);fclose(stdout);
return ;
}
/*维护两个数组 很好的解决了重复计算的问题*/
#include<iostream>
#include<cstdio>
#define ld long double
#define maxn 210
using namespace std;
int n,k;
ld f[maxn][maxn],ff[maxn][maxn],g[maxn][maxn][];
int main(){
freopen("brackets.in", "r", stdin);
freopen("brackets.out", "w", stdout);
cin>>n>>k;
for(int i=;i<=n;i++)
for(int j=;j<=k;j++)
cin>>g[i][j][]>>g[i][j][];
for(int i=;i<n;i++)
for(int x=;x<=k;x++)
f[i][i+]+=g[i][x][]*g[i+][x][];
for(int i=n-;i>=;i--)
for(int j=i+;j<=n;j++){
for(int x=;x<=k;x++)
f[i][j]+=(f[i+][j-]+ff[i+][j-])*g[i][x][]*g[j][x][];
for(int x=i+;x<j-;x++)
ff[i][j]+=(f[i][x]+ff[i][x])*f[x+][j];
}
printf("%.5f\n",(double)(f[][n]+ff[][n]));
return ;
}

测试题 #4 城堡
城堡
【问题描述】
给定一张?个点?条边的无向连通图,每条边有边权。我们需要从?条边中
选出? − 1条, 构成一棵树。 记原图中从 1 号点到每个节点的最短路径长度为? ? ,
树中从 1 号点到每个节点的最短路径长度为? ? ,构出的树应当满足对于任意节点
?,都有? ? = ? ? 。
请你求出选出? − 1条边的方案数。
【输入格式】
输入的第一行包含两个整数?和?。
接下来?行,每行包含三个整数?、?和?,描述一条连接节点?和?且边权为
?的边。
【输出格式】
输出一行,包含一个整数,代表方案数对2 31 − 1取模得到的结果。
【样例输入】
3 3
1 2 2
1 3 1
2 3 1
【样例输出】
2
【数据规模和约定】
32 ≤ ? ≤ 5,? ≤ 10。
对于50%的数据,满足条件的方案数不超过 10000。
对于100%的数据,2≤ ? ≤ 1000,? − 1 ≤ ? ≤
? ?−1
2
,1 ≤ ? ≤ 100。

/*暴力 dfs+SPFA+Tarjan+dfs*/
#include<cstdio>
#include<queue>
#include<iostream>
#include<cstring>
#define maxn 1010
using namespace std;
int n,m,num,head[maxn],f[maxn],D[maxn],S[maxn],topt,top;
int s[maxn],vis[maxn],dfn[maxn],low[maxn],sum,Sum[maxn];
long long ans;
struct node{
int u,v,t;
}p[maxn];
struct edge{
int v,t,pre,x;
}e[maxn*];
queue<int>q;
int init(){
int x=,f=;char s=getchar();
while(s<''||s>''){if(s=='-')f=-;s=getchar();}
while(s>=''&&s<=''){x=x*+s-'';s=getchar();}
return x*f;
}
void Add(int from,int to,int dis,int i){
num++;e[num].v=to;
e[num].x=i;
e[num].t=dis;
e[num].pre=head[from];
head[from]=num;
}
void Tarjan(int x,int fa){
dfn[x]=low[x]=++topt;
s[++top]=x;vis[x]=;
for(int i=head[x];i;i=e[i].pre){
int v=e[i].v;
if(v==fa||!f[e[i].x])continue;
if(dfn[v]==){
Tarjan(v,x);low[x]=min(low[x],low[v]);
}
else if(vis[v])low[x]=min(low[x],dfn[v]);
}
if(low[x]==dfn[x]){
sum++;while(x!=s[top]){
Sum[sum]++;vis[s[top]]=;top--;
}
Sum[sum]++;vis[s[top]]=;top--;
}
}
bool Judge(){
memset(dfn,,sizeof(dfn));
memset(low,,sizeof(low));
memset(s,,sizeof(s));
memset(vis,,sizeof(vis));
memset(Sum,,sizeof(Sum));
topt=top=sum=;
for(int i=;i<=n;i++)
if(dfn[i]==)Tarjan(i,);
for(int i=;i<=sum;i++)
if(Sum[i]>)return ;
return ;
}
void SPFA(){
memset(D,/,sizeof(D));
D[]=;f[]=;q.push();
while(!q.empty()){
int k=q.front();q.pop();f[k]=;
for(int i=head[k];i;i=e[i].pre){
int v=e[i].v;
if(D[v]>D[k]+e[i].t){
D[v]=D[k]+e[i].t;
if(f[v]==){
f[v]=;q.push(v);
}
}
}
}
}
void dfs(int now,int from,int x){
S[now]=min(S[now],x);
for(int i=head[now];i;i=e[i].pre){
if(!f[e[i].x])continue;
int v=e[i].v;if(v==from)continue;
dfs(v,now,x+e[i].t);
}
}
void Solve(){
memset(S,/,sizeof(S));
S[]=;dfs(,,);
for(int i=;i<=n;i++)
if(S[i]!=D[i])return;
ans++;return;
}
void Dfs(int now){
if(now==m+){
int cnt=;
for(int i=;i<=m;i++)
if(f[i])cnt++;
if(cnt!=n-||!Judge())return;
Solve();return;
}
f[now]=;Dfs(now+);
f[now]=;Dfs(now+);
}
int main()
{
freopen("castle.in","r",stdin);
freopen("castle.out","w",stdout);
n=init();m=init();
int u,v,t;
for(int i=;i<=m;i++){
u=init();v=init();t=init();
p[i].u=u;p[i].v=v;p[i].t=t;
Add(u,v,t,i);Add(v,u,t,i);
}
SPFA();memset(f,,sizeof(f));Dfs();
cout<<ans<<endl;
fclose(stdin);fclose(stdout);
return ;
}
/*
很机智的题解
维护每个点连出去的边中 有几个是最短路上的
假设 两个点 ij i有a条连边是最短路上的 j有b条
那么 1 i j 这三个点构成一棵树就有 1*a*b中方法
加上其他的点同理
最后乘法原理算一下
*/
#include<cstdio>
#include<queue>
#include<iostream>
#include<cstring>
#define ll long long
#define mod ((1<<31)-1)
#define maxn 1010
using namespace std;
int n,m,num,head[maxn],f[maxn],D[maxn],c[maxn];
ll ans=;
struct node{
int u,v,t;
}p[maxn*maxn];
struct edge{
int v,t,pre;
}e[maxn**maxn];
queue<int>q;
int init(){
int x=,f=;char s=getchar();
while(s<''||s>''){if(s=='-')f=-;s=getchar();}
while(s>=''&&s<=''){x=x*+s-'';s=getchar();}
return x*f;
}
void Add(int from,int to,int dis){
num++;e[num].v=to;
e[num].t=dis;
e[num].pre=head[from];
head[from]=num;
}
void SPFA(){
memset(D,/,sizeof(D));
D[]=;f[]=;q.push();
while(!q.empty()){
int k=q.front();q.pop();f[k]=;
for(int i=head[k];i;i=e[i].pre){
int v=e[i].v;
if(D[v]>D[k]+e[i].t){
D[v]=D[k]+e[i].t;
if(f[v]==){
f[v]=;q.push(v);
}
}
}
}
}
int main()
{
freopen("castle.in","r",stdin);
freopen("castle.out","w",stdout);
n=init();m=init();
int u,v,t;
for(int i=;i<=m;i++){
u=init();v=init();t=init();
p[i].u=u;p[i].v=v;p[i].t=t;
Add(u,v,t);Add(v,u,t);
}
SPFA();
for(int i=;i<=m;i++){
if(D[p[i].v]==D[p[i].u]+p[i].t)c[p[i].v]++;
if(D[p[i].u]==D[p[i].v]+p[i].t)c[p[i].u]++;
}
for(int i=;i<=n;i++)
ans=ans*(ll)c[i]%mod;
cout<<ans<<endl;
fclose(stdin);fclose(stdout);
return ;
}

11.13 noip模拟试题的更多相关文章

  1. 11.14 noip模拟试题

      题目名称 正确答案 序列问题 长途旅行 英文名称 answer sequence travel 输入文件名 answer.in sequence.in travel.in 输出文件名 answer ...

  2. 11.12 noip模拟试题

    题目名称 加密 冒泡排序图 重建可执行文件名 encrypt bubble rebuild输入文件名 encrypt.in bubble.in rebuild.in输出文件名 encrypt.in b ...

  3. 11.9 noip模拟试题

    NOIP2016 模拟赛——那些年,我们学过的文化课背单词(word.c/cpp/pas)[题目描述]fqk 退役后开始补习文化课啦, 于是他打开了英语必修一开始背单词. 看着满篇的单词非常头疼, 而 ...

  4. 11.10 noip模拟试题

    1.第K小数 (number.cpp/c/pas) [问题描述] 有两个正整数数列,元素个数分别为N和M.从两个数列中分别任取一个数 相乘,这样一共可以得到N*M个数,询问这N*M个数中第K小数是多少 ...

  5. 10.13 noip模拟试题

    Porble 1时间与空间之旅(tstrip.*) 题目描述 公元22××年,宇宙中最普遍的交通工具是spaceship.spaceship的出现使得星系之间的联系变得更为紧密,所以spaceship ...

  6. 11.7 NOIP模拟赛

    目录 2018.11.7 NOIP模拟 A 序列sequence(two pointers) B 锁lock(思路) C 正方形square(埃氏筛) 考试代码 B C 2018.11.7 NOIP模 ...

  7. 11/1 NOIP 模拟赛

    11.1 NOIP 模拟赛 期望得分:50:实际得分:50: 思路:暴力枚举 + 快速幂 #include <algorithm> #include <cstring> #in ...

  8. 10.11 noip模拟试题

    4题均为128M,1s 1. 锻炼计划(exercise.pas) 身体是革命的本钱,OIers不要因为紧张的学习和整天在电脑前而忽视了健康问题.小x设计了自己的锻炼计划,但他不知道这个计划是否可行, ...

  9. 10.4 noip模拟试题

    题目名称 PA 青春 三部曲 名称 huakai taritari truetears 输入 huakai.in taritari.in truetears.in 输出 huakai.out tari ...

随机推荐

  1. Linux内核与根文件系统的关系

    开篇题外话:对于Linux初学者来说,这是一个很纠结的问题,但这也是一个很关键的问题!         一语破天机: “尽管内核是 Linux 的核心,但文件却是用户与操作系统交互所采用的主要工具.这 ...

  2. 【转】Eclipse提示No java virtual machine(转载)

    原文网址:http://blog.sina.com.cn/s/blog_6cd73dfb01013zkg.html 第一次运行Eclipse,经常会提示下面的问题:... No java virtua ...

  3. ArrayList源码解析

    ArrayList简介 ArrayList定义 1 public class ArrayList<E> extends AbstractList<E> implements L ...

  4. zabbix 获取不到自定义脚本的值解决

    agent端: zabbix 自定义脚本 [root@localhost script]# cat check_ping.sh #!/bin/bash result=$(/usr/local/nagi ...

  5. 页面置换算法(最佳置换算法、FIFO置换算法、LRU置换算法、LFU置换算法)

    页面置换产生的原因是:分页请求式存储管理(它是实现虚拟存储管理的方法之一,其中一个特性是多次性-->多次将页面换入或换出内存) 效果最好的页面置换算法:最佳置换算法 比较常用的页面置换算法有:F ...

  6. ubuntu下使用脚本交叉编译windows下使用的ffmpeg + X264

    这里主要是补充一些遇到的问题和解决方法. 2013-06 下旬 由于项目需要,重新编译ffmpeg+264+其他. 这里使用的环境Ubuntu 13.04,脚本依然是cross_compile_ffm ...

  7. 表达式计算器(LL1文法)

    LL(1)文法求算数表达式的值递归子程序法 分析过程: 表达式文法G[E]:E->E+T|E-T|TT->T*F|T/F|T%F|FF->N^F|NN->(E)|NUM|+NU ...

  8. poj1087 A Plug for UNIX & poj1459 Power Network (最大流)

    读题比做题难系列…… poj1087 输入n,代表插座个数,接下来分别输入n个插座,字母表示.把插座看做最大流源点,连接到一个点做最大源点,流量为1. 输入m,代表电器个数,接下来分别输入m个电器,字 ...

  9. PC-经典之“运行里面的密密”

    msconfig.exe 你自己往里面输入这个字母就可以看到了,试试看,还有,我这里有一些可以在"运行"栏里输入的命令,一并给你: 以下为Windows操作系统的常用运行命令,执行 ...

  10. IE-一根网线二台电脑上网

    1 直连线 使用交叉线(橙白 橙 (蓝白) (绿 绿白) ( 蓝)宗白 棕) 2 如果主机原本是用ADSL拔号上网的话,就在主机的网络连接下的宽带连接右击属性>高级,在“Internet 连接共 ...