1840:【05NOIP提高组】过河
在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧。在桥上有一些石子,青蛙很讨厌踩在这些石子上。由于桥的长度和青蛙一次跳过的距离都是正整数,我们可以把独木桥上青蛙可能到达的点看成数轴上的一串整点:0,1,……,L(其中L是桥的长度)。坐标为0的点表示桥的起点,坐标为L的点表示桥的终点。青蛙从桥的起点开始,不停的向终点方向跳跃。一次跳跃的距离是S到T之间的任意正整数(包括S,T)。当青蛙跳到或跳过坐标为L的点时,就算青蛙已经跳出了独木桥。
题目给出独木桥的长度L,青蛙跳跃的距离范围S,T,桥上石子的位置。你的任务是确定青蛙要想过河,最少需要踩到的石子数。
#include<iostream>
#include<algorithm>
using namespace std;
int a[110],d[110],stone[350000];
int f[350000];
int main()
{
int l,s,t,m;cin>>l>>s>>t>>m;
for (int i=1;i<=m;i++)cin>>a[i];
sort(a+1,a+m+1);
for (int i=1;i<=m;i++)d[i]=(a[i]-a[i-1])%2520;
for (int i=1;i<=m;i++)
{
a[i]=a[i-1]+d[i];
stone[a[i]]=1;
}
l=a[m];
for (int i=0;i<=l+t;i++) f[i]=m;
f[0]=0;
for (int i=1;i<=l+t;i++)
for (int j=s;j<=t;j++)
{
if (i-j>=0)
f[i]=min(f[i],f[i-j]);
f[i]+=stone[i];
}
int ans=m;
for (int i=l;i<l+t;i++) ans=min(ans,f[i]);
cout<<ans<<endl;
return 0;
}
1841:【05NOIP提高组】篝火晚会
佳佳刚进高中,在军训的时候,由于佳佳吃苦耐劳,很快得到了教官的赏识,成为了“小教官”。在军训结束的那天晚上,佳佳被命令组织同学们进行篝火晚会。一共有n个同学,编号从1到n。一开始,同学们按照1,2,……,n的顺序坐成一圈,而实际上每个人都有两个最希望相邻的同学。如何下命令调整同学的次序,形成新的一个圈,使之符合同学们的意愿,成为摆在佳佳面前的一大难题。
佳佳可向同学们下达命令,每一个命令的形式如下:
(b1, b2,... bm -1, bm)
这里m的值是由佳佳决定的,每次命令m的值都可以不同。这个命令的作用是移动编号是b1,b2,…… bm –1,bm的这m个同学的位置。要求b1换到b2的位置上,b2换到b3的位置上,……,要求bm换到b1的位置上。
执行每个命令都需要一些代价。我们假定如果一个命令要移动m个人的位置,那么这个命令的代价就是m。我们需要佳佳用最少的总代价实现同学们的意愿,你能帮助佳佳吗?
#include<bits/stdc++.h>
using namespace std;
int i,j,m,n,temp;
int a[50001],x[50001],y[50001];
int gs[50001],gs2[50001];
int r()
{
int ans=0,f=1;
char ch;
while(ch<'0'||ch>'9')
{
if(ch=='-')
f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
ans*=10;
ans+=ch-'0';
ch=getchar();
}
return ans*f;
}
int main()
{
n=r();
for(i=1;i<=n;i++)
{
x[i]=r(),y[i]=r();
}
a[1]=1,a[2]=x[1];
for(i=3;i<=n;i++)
{
if(x[a[i-1]]==a[i-2]) a[i]=y[a[i-1]];
else a[i]=x[a[i-1]];
}
int le,ri;
for(i=1;i<=n;i++)
{
le=i-1;
ri=i+1;
if(!le)
le=n;
if(ri==n+1)
ri=1;
if((x[a[i]]!=a[ri]||a[le]!=y[a[i]])&&
(y[a[i]]!=a[ri]||a[le]!=x[a[i]]))
{
cout<<-1;
return 0;
}
}
int dis1,dis2;
for (i=1; i<=n; i++)
{
dis1=(a[i]-i+n)%n;
dis2=(a[i]+i-1)%n;
gs[dis1]++;
gs2[dis2]++;
}
int ans=0;
for (i=0; i<n; i++)
{
if (ans<gs[i]) ans=gs[i];
if (ans<gs2[i]) ans=gs2[i];
}
cout<<n-ans;
return 0;
}
1842:【05NOIP提高组】等价表达式
明明进了中学之后,学到了代数表达式。有一天,他碰到一个很麻烦的选择题。这个题目的题干中首先给出了一个代数表达式,然后列出了若干选项,每个选项也是一个代数表达式,题目的要求是判断选项中哪些代数表达式是和题干中的表达式等价的。
这个题目手算很麻烦,因为明明对计算机编程很感兴趣,所以他想是不是可以用计算机来解决这个问题。假设你是明明,能完成这个任务吗?
这个选择题中的每个表达式都满足下面的性质:
1. 表达式只可能包含一个变量‘a’。
2. 表达式中出现的数都是正整数,而且都小于10000。
3. 表达式中可以包括四种运算‘+’(加),‘-’(减),‘*’(乘),‘^’(乘幂),以及小括号‘(’,‘)’。小括号的优先级最高,其次是‘^’,然后是‘*’,最后是‘+’和‘-’。‘+’和‘-’的优先级是相同的。相同优先级的运算从左到右进行。(注意:运算符‘+’,‘-’,‘*’,‘^’以及小括号‘(’,‘)’都是英文字符)
4. 幂指数只可能是1到10之间的正整数(包括1和10)。
5. 表达式内部,头部或者尾部都可能有一些多余的空格。
下面是一些合理的表达式的例子:
((a^1) ^ 2)^3,a*a+a-a,((a+a)),9999+(a-a)*a,1 + (a -1)^3,1^10^9……
#include<iostream>
#include<cstdio>
#include<cstring>
#define N 2147483647
#define MOD 32767
typedef long long LL;
using namespace std;
LL top,t=0,flag;
char stack_sign[100006],s[10006];
LL stack_num[100006];
int n;
LL ans1,ans2,m1,m2,ans3,m3;
LL pow(LL x,LL y)
{
LL sum=1;
for (int i=1;i<=y;i++)
sum*=x;
return sum;
}
//int get()
//{
// int x=0,f=1;
// char c;
// c=getchar();
// while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
// while (c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}
// return x*f;
//}
int level(char c) //赋予每个符号一个优先级
{
if (c=='+'||c=='-') return 1;
if (c=='*') return 2;
if (c=='^') return 3;
if (c=='(') return 0;
}
LL ksm(int a,int b,int c)
{
int ans=1;
a=a%c;
while (b>0)
{
if (b&1) ans=(ans*a)%c;
b=b/2;
a=(a*a)%c;
}
return ans%c;
}
int clac(int x,int y,char cc)
{
int ans;
if (cc=='+') ans=(x+y)%MOD;
if (cc=='-') ans=(y-x+MOD)%MOD;
if (cc=='*') ans=(x%MOD*y%MOD)%MOD;
if (cc=='^') ans=ksm(y,x,MOD);
return ans%MOD;
}
LL love()
{
char c;
int tmp;
t=0;
top=0;
memset(stack_num,0,sizeof(stack_num));
memset(stack_sign,'\0',sizeof(stack_sign));
c=getchar();
while(c=='\n'||c=='\r') c=getchar();
while (c!='\n'&&c!='\r')
{
if (c==' ') {c=getchar();continue;}
if (c>='0'&&c<='9')
{