Day1
1.xth的阶梯 (stair.pas/c/cpp)
描述
Xth家有一个很长很长的楼梯,有n级,现在你想要走完这个阶梯。
开始时你在0级,你可以一步走一级或两级。最后一步必须恰好落到第n级上
请你求出有多少种行走方案可以走完这个阶梯。为了降低编程复杂度,只需输出最后的结果mod 123456的值即可
输入格式(stair.in)
第一行:
一个整数n
输出格式(stair.out)
一行:最后的结果
样例输入
2
样例输出
2
数据范围
50%的数据:n<=2^20;
100%的数据:n<=2^64-1;
//斐波那契数列
program __stair;
type
arr=array[1..2,1..2] of int64;var
a,b:arr;n,ans:int64;procedure multity(var a,b:arr);var
c:arr;i,j,k:longint;begin
fillchar(c,sizeof(c),0);for i:=1 to 2 dofor j:=1 to 2 dofor k:=1 to 2 doc[i][j]:=(c[i][j]+a[i][k]*b[k][j]) mod 123456;
a:=c;end;
procedure power(i:int64);
var
t:arr;begin
t:=a;b:=a;dec(i);while (i>0) dobegin
if (i and 1=1) then multity(b,t);i:=i shr 1;
multity(t,t);end;
end;
begin
assign(input,'stair.in');
reset(input);assign(output,'stair.out');rewrite(output);readln(n);close(input);if (n<2) thenbegin
writeln(1);close(output);halt;end;
dec(n);a[1][1]:=1;a[1][2]:=1;a[2][1]:=1;a[2][2]:=0;power(n);ans:=(b[1][1]+b[2][1]) mod 123456;
writeln(ans);close(output);end.
2.pizza
描述:
Dsqwwe从小到大都没有吃过披萨,今天,他终于忍不住了,于是他叫了一份必胜客的外卖,由于不是dsqwwe一个人叫外卖,送外卖的小哥要到每个叫外卖的顾客家中然后最后回到必胜客…..这里有n-1个顾客叫外卖,必胜客在1号路口,叫外卖的顾客家分别在2,3,4…..n号路口,每两个路口都有一条通路,小哥想保证送外卖的时间最少,问最少时间为多少(一个路口可以多次经过的)
输入:
第一行:n(2<=n<=15)
接下来n行每行n个数,第i行第j列代表从i到j的时间,当然这个矩阵是沿对角线对称的,且i行i列为0,除此外都不为0
输出:
最少时间
样例输入:
4
0 1 10 10
1 0 1 2
10 1 0 10
10 2 10 0
样例输出:
8
//二维记录状态SPFA
#include <cstdio>#include <cstring>#include <iostream>using namespace std;int n;
int a[16][16];
int d[32769][16];
struct node{
int x,id;
}f[1100000];bool v[32769][16];
void SPFA(){
memset(d,63,sizeof(d));
d[1][1]=0;f[1].x=1;f[1].id=1;int head=0,tail=1;
while (head<tail){
int x=f[++head].x;
int id=f[head].id;
v[id][x]=false;
for (int i=1;i<=n;i++)if (i!=x){if (d[id | (1 << (i -1))][i]>d[id][x]+a[x][i]){
d[id | (1 << (i-1))][i]=d[id][x]+a[x][i];if (!v[id | (1 << (i-1))][i]){
v[id | (1 << (i-1))][i]=true;
f[++tail].x=i;f[tail].id=id | (1 << (i-1));}}}}}int main(){
freopen("pizza.in","r",stdin);freopen("pizza.out","w",stdout);cin>>n;for (int i=1;i<=n;i++){for (int j=1;j<=n;j++){cin>>a[i][j];}}SPFA();int ans=d[(1 << n)-1][1];
printf("%d\n",ans);
return 0;
}
//状态压缩DP+floyd最短路
var
a:array[1..15,1..15] of longint;f:array[0..65535,1..15] of longint;n,i,j,k,ans,lim:longint;function min(a,b:longint):longint;
begin
if (a<b) then exit(a) else exit(b);end;
begin
assign(input,'pizza.in');
reset(input);assign(output,'pizza.out');rewrite(output);readln(n);for i:=1 to n dofor j:=1 to n dobegin
read(a[i][j]);end;
for k:=1 to n dofor i:=1 to n doif (i<>k) thenfor j:=1 to n doif (j<>k) and (i<>j) thenif (a[i][k]+a[k][j]<a[i][j]) then a[i][j]:=a[i][k]+a[k][j];fillchar(f,sizeof(f),63);lim:=1 shl n-1;
f[1][1]:=0;for i:=1 to lim dofor j:=1 to n doif ((i and (1 shl (j-1)))=(1 shl (j-1))) thenbegin
for k:=1 to n doif ((i and (1 shl (k-1)))=0) thenbegin
f[i or (1 shl (k-1))][k]:=min(f[i or (1 shl (k-1))][k],f[i][j]+a[k][j]);end;
end;
ans:=maxlongint;for i:=1 to n-1 doif (ans>f[lim][i]+a[i][1]) then ans:=f[lim][i]+a[i][1];writeln(ans);close(input);close(output);end.
3.xth的苹果树(apple.pas/c/cpp)
描述
xth种了一棵苹果树,这棵树由n个节点构成,中间有树枝连接,苹果都会长在节点上,并且不会有两个苹果长在同一个节点上。Xth想知道某个子树上有多少个苹果,你能帮帮他吗?(1号节点为跟)
输入格式(apple.in)
第一行:一个整数n,表示苹果树有n个节点。
以下n-1行:每行两个整数u、v,表示u、v两节点间有树枝相连。
第n+1行:一个整数m,表示有m个询问或操作。
以下m行:一个字符(’C’或’Q’)和一个整数x。‘C’表示将x节点处的苹果有无情况取反。‘Q’表示询问以x为根的子树中苹果的个数。
注:苹果树开始时是长满苹果的。
输出格式(apple.out)
对于每一个询问输出一行,一个整数,表示苹果数。
输入样例
3
1 2
1 3
3
Q 1
C 2
Q 1
输出样例
3
2
数据规模
N<=100000,M<=100000
//树状数组
//模拟(低效率刚刚过0.98s)#include <cstdio>#include <cstring>#include <iostream>using namespace std;int n,m;
struct edge{
int x,next;
}e[200000],e2[200000];int tot,tot2;
int first[110000],first2[110000];
int a[110000];
int fa[110000];
int l[110000],r[110000];
int v[110000];
void add2(int a,int b){e2[++tot2].x=b;e2[tot2].next=first2[a];first2[a]=tot2;}void add(int a,int b){e[++tot].x=b;e[tot].next=first[a];first[a]=tot;}bool vis[110000];
void build(int x){vis[x]=true;
for (int t=first2[x];t;t=e2[t].next){if (!vis[e2[t].x]){
fa[e2[t].x]=x;add(x,e2[t].x);build(e2[t].x);}}}int cnt;
void makeque(int x){r[x]=cnt;l[x]=cnt;--cnt;for (int t=first[x];t;t=e[t].next){makeque(e[t].x);l[x]=min(l[x],l[e[t].x]);}}inline int lowbit(int x){return x & (x ^ (x-1));}void Plus(int x,int k){while (x<=n){
a[x]+=k;x+=lowbit(x);}}int sum(int x){int tot=0;
while (x>0){
tot+=a[x];x-=lowbit(x);}return tot;
}int main(){
freopen("apple.in","r",stdin);freopen("apple.out","w",stdout);scanf("%d",&n);
for (int i=1;i<n;i++){int x,y;
scanf("%d%d",&x,&y);
add2(x,y);add2(y,x);}build(1);cnt=n;makeque(1);for (int i=1;i<=n;i++){Plus(i,1);}scanf("%d\n",&m);
for (int i=1;i<=m;i++){char ch;
int x;
scanf("%c %d\n",&ch,&x);
if (ch=='C'){
if (!v[r[x]]){
Plus(r[x],-1);v[r[x]]=1;}else{
Plus(r[x],1);v[r[x]]=0;}}else{
int ans=sum(r[x])-sum(l[x]-1);
printf("%d\n",ans);
}}return 0;
}
program __apple;
type
edge=record
x,next:longint;end;
var
e,e2:array[0..200000] of edge;first,first2:array[0..110000] of longint;tot,tot2:longint;fa:array[0..110000] of longint;num:array[0..110000] of longint;a:array[0..110000] of longint;v:array[0..110000] of boolean;i,n,m,x,y:longint;ch:char;procedure add(a,b:longint);
begin
inc(tot);e[tot].x:=b;e[tot].next:=first[a];first[a]:=tot;end;
procedure add2(a,b:longint);
begin
inc(tot2);e2[tot2].x:=b;e2[tot2].next:=first2[a];first2[a]:=tot2;end;
procedure build(x:longint);
var
t:longint;begin
v[x]:=true;num[x]:=1;t:=first2[x];while (t<>0) dobegin
if (not v[e2[t].x]) thenbegin
add(x,e2[t].x);fa[e2[t].x]:=x;build(e2[t].x);inc(num[x],num[e2[t].x]);end;
t:=e2[t].next;end;
end;
{procedure makenum(x:longint);
var
t:longint;begin
num[x]:=1;t:=first[x];while (t<>0) dobegin
makenum(e[t].x);inc(num[x],num[e[t].x]);t:=e[t].next;end;
end;
}procedure change(x,y:longint);
var
i:longint;begin
inc(num[x],y);i:=fa[x];while (i<>0) dobegin
inc(num[i],y);i:=fa[i];end;
end;
begin
assign(input,'apple.in');
reset(input);assign(output,'apple.out');rewrite(output);readln(n);for i:=1 to n-1 dobegin
readln(x,y);add2(x,y);add2(y,x);end;
build(1);//makenum(1);
readln(m);for i:=1 to m dobegin
readln(ch,x);if (ch='Q') thenwriteln(num[x])else
begin
if (a[x]=0) thenbegin
change(x,-1);a[x]:=1;end
else
begin
change(x,1);a[x]:=0;end;
end;
end;
close(input);close(output);end.
Day2
1.xth的舞会(party.pas/c/cpp)
描述
xth准备开一个舞会。
他准备邀请n个已经确定的人,可是问题来了:
这n个人每一个人都有一个小花名册,名册里面写着他所愿意交流的人的名字。比如说在A的人名单里写了B,那么表示A愿意与B交流;但是B的名单里不见的有A,也就是说B不见的想与A交流。但是如果A愿意与B交流,B愿意与C交流,那么A一定愿意与C交流。也就是说交流有传递性。
Xth觉得需要将这n个人分为m组,要求每一组的任何一人都愿意与组内其他人交流。并求出一种方案以确定m的最小值是多少。
注意:自己的名单里面不会有自己的名字。
输入格式(party.in)
第一行一个数n。接下来n行,每i+1行表示编号为i的人的小花名册名单,名单以0结束。1<=n<=200。
输出格式(party.out)
一个数,m。
输入样例
18
0
18 0
0
0
11 0
0
0
0
0
0
5 0
0
0
0
0
0
0
2 0
输出样例
16
数据规模
1<=n<=200
//tarjan
program __party;
type
Edge=record
x,next:longint;end;
var
e:array[0..100000] of Edge;first:array[0..210] of longint;n,i,cnt,times,top,x,tot:longint;stack,low,dfn:array[0..210] of longint;instack:array[0..210] of boolean;function min(a,b:longint):longint;
begin
if (a<b) then exit(a) else exit(b);end;
procedure add(a,b:longint);
begin
inc(tot);e[tot].x:=b;e[tot].next:=first[a];first[a]:=tot;end;
procedure tarjan(u:longint);
var
t,i,v:longint;begin
inc(times);dfn[u]:=times;low[u]:=times;instack[u]:=true;inc(top);stack[top]:=u;t:=first[u];while (t<>0) dobegin
v:=e[t].x;if (dfn[v]=0) thenbegin
tarjan(v);low[u]:=min(low[u],low[v]);end
else
if (instack[v]) then low[u]:=min(low[u],dfn[v]);t:=e[t].next;end;
if (low[u]=dfn[u]) thenbegin
inc(cnt);repeat
i:=stack[top];instack[i]:=false;dec(top);until i=u;
end;
end;
begin
assign(input,'party.in');
reset(input);assign(output,'party.out');rewrite(output);readln(n);for i:=1 to n dobegin
read(x);while (x<>0) dobegin
add(i,x);read(x);end;
readln;end;
for i:=1 to n doif (dfn[i]=0) then tarjan(i);writeln(cnt);close(input);close(output);end.
2.climbing(climbing.pas/c/cpp)
描述:
Dsqwwe很喜欢旅游,这次他和他的朋友去爬山,途中遇到一处悬崖,dsqwwe决定挑战自己。这处悬崖可以描述为一个n*m的矩阵,矩阵中s代表落脚点,t代表终点,数字带表一只脚落到上面所需时间,X代表此处无法落脚。攀登时,先把左脚或右脚放在任意一处s处,然后另一只脚开始攀登,攀登时,当然是左脚一步,右脚一步。
若一只脚在(x1,y1),另一只脚落地的范围要保证 |x1-x2|+|y1-y2|<=3,若左脚固定,迈右脚只能往右边迈。右脚固定迈左脚只能向左边迈,如图:
当任意一只脚落在t处,则攀登结束,为攀登所需的最少时间为多少
输入(climbing.in):
注意多组数据
对于每组数据,第一行为两个整数,n,m(0<=n,m<=100)
然后就是一个n*m的矩阵,描述悬崖
输出(climbing.out):
若无法完成攀登,输出-1
若可以完成攀登,输出最小时间
样例输入:
6 6
4 4 X X T T
4 7 8 2 X 7
3 X X X 1 8
1 2 X X X 6
1 1 2 4 4 7
S S 2 3 X X
2 10
T 1
1 X
1 X
1 X
1 1
1 X
1 X
1 1
1 X
S S
2 10
T X
1 X
1 X
1 X
1 1
1 X
1 X
1 1
1 X
S S
10 10
T T T T T T T T T T
X 2 X X X X X 3 4 X
9 8 9 X X X 2 9 X 9
7 7 X 7 3 X X 8 9 X
8 9 9 9 6 3 X 5 X 5
8 9 9 9 6 X X 5 X 5
8 6 5 4 6 8 X 5 X 5
8 9 3 9 6 8 X 5 X 5
8 3 9 9 6 X X X 5 X
S S S S S S S S S S
10 7
2 3 2 3 2 3 2 3 T T
1 2 3 2 3 2 3 2 3 2
3 2 3 2 3 2 3 2 3 4
3 2 3 2 3 2 3 2 3 5
3 2 3 1 3 2 3 2 3 5
2 2 3 2 4 2 3 2 3 5
S S 2 3 2 1 2 3 2 3
样例输出:
12
5
-1
22
12
样例解释
第一组(l代表左脚,r代表右脚):
4 4 X X T T
4 7 8 2 X 7
3 X X X 1 8
1 R X X X 6
1 1 2 4 4 7
L S 2 3 X X
4 4 X X T T
L 7 8 2 X 7
3 X X X 1 8
1 R X X X 6
1 1 2 4 4 7
S S 2 3 X X
4 4 X X T T
L 7 8 R X 7
3 X X X 1 8
1 2 X X X 6
1 1 2 4 4 7
S S 2 3 X X
4 L X X T T
4 7 8 R X 7
3 X X X 1 8
1 2 X X X 6
1 1 2 4 4 7
S S 2 3 X X
4 L X X R T
4 7 8 2 X 7
3 X X X 1 8
1 2 X X X 6
1 1 2 4 4 7
S S 2 3 X X
//BFS
program __climbing;
const
dil:array[1..9] of longint=(0,1,2,-1,-2,0,-1,1,0);djl:array[1..9] of longint=(-1,-1,-1,-1,-1,-2,-2,-2,-3);dir:array[1..9] of longint=(0,1,2,-1,-2,0,-1,1,0);djr:array[1..9] of longint=(1,1,1,1,1,2,2,2,3);maxq=1000000;type
node=record
x,y,num:longint;end;
var
q:array[0..maxq] of node;a:array[0..110,0..110] of longint;v:array[0..110,0..110,0..1] of longint;n,m,i,j,head,tail,k,x,y,tx,ty,p,ans:longint;s:ansistring;flag:boolean;begin
assign(input,'climbing.in');
reset(input);assign(output,'climbing.out');rewrite(output);while (not eof) dobegin
tail:=0;head:=0;flag:=false;ans:=maxlongint;fillchar(a,sizeof(a),0);fillchar(v,sizeof(v),63);readln(n,m);for i:=1 to n dobegin
readln(s);s:=s+' ';for j:=1 to m dobegin
if (s[1]='X') thenbegin
a[i][j]:=-1;delete(s,1,2);end
else
if (s[1]='S') thenbegin
a[i][j]:=0;v[i][j][0]:=0;v[i][j][1]:=0;inc(tail);q[tail].x:=i;q[tail].y:=j;q[tail].num:=0;inc(tail);q[tail].x:=i;q[tail].y:=j;q[tail].num:=1;delete(s,1,2);end
else
if (s[1]='T') thenbegin
a[i][j]:=500;delete(s,1,2);end
else
begin
k:=1;while (s[k] in ['0'..'9']) do inc(k);val(copy(s,1,k-1),a[i][j]);delete(s,1,k);end;
end;
end;
while (head<>tail) dobegin
inc(head);if (head=maxq) then head:=1;if (q[head].num=0) thenbegin
x:=q[head].x;y:=q[head].y;for p:=1 to 9 dobegin
tx:=x+dir[p];ty:=y+djr[p];if (tx>0)and(ty>0)and(tx<=n)and(ty<=m)and(a[tx][ty]<>-1) thenbegin
if (a[tx][ty]=500) thenbegin
flag:=true;if (ans>v[x][y][0]) then ans:=v[x][y][0];continue;end;
if (v[tx][ty][1]>v[x][y][0]+a[tx][ty]) thenbegin
v[tx][ty][1]:=v[x][y][0]+a[tx][ty];inc(tail);if (tail=maxq) then tail:=1;q[tail].x:=tx;q[tail].y:=ty;q[tail].num:=1;end;
end;
end;
end
else
begin
x:=q[head].x;y:=q[head].y;for p:=1 to 9 dobegin
tx:=x+dil[p];ty:=y+djl[p];if (tx>0)and(ty>0)and(tx<=n)and(ty<=m)and(a[tx][ty]<>-1) thenbegin
if (a[tx][ty]=500) thenbegin
flag:=true;if (ans>v[x][y][1]) then ans:=v[x][y][1];continue;end;
if (v[tx][ty][0]>v[x][y][1]+a[tx][ty]) thenbegin
v[tx][ty][0]:=v[x][y][1]+a[tx][ty];inc(tail);if (tail=maxq) then tail:=1;q[tail].x:=tx;q[tail].y:=ty;q[tail].num:=0;end;
end;
end;
end;
end;
if (flag) then writeln(ans) else writeln(-1);end;
close(input);close(output);end.
3.solve(solve.pas/c/cpp)
描述
dsqwwe每个月都有m(0<=m<=1000)元的零花钱,他现在有n(n<=300)项消费计划,每个消费计划消耗2种费用,一种是要花掉当前月的零花钱,另一种是要花掉下一个月的零花钱,每个月的零花钱不能超支,若一个月的零花钱不能用完,dsqwwe会把钱花在其他地方,也就是说,每个月剩余的零花钱不会留给下一个月。问dsqwwe想要完成他所有的消费计划最少需要几个月。
输入(solve.in):
第一行:m,n
接下来的n行,每行两个整数a,b,描述一种消费计划,a代表花掉当前月的钱的数目,b代表花掉下个月的钱的数目(a,b<=m)
输出(solve.out):
需要最少的月数
样例输入:
100 5
40 20
60 20
30 50
30 50
40 40
样例输出:
5
样例解释:
+------+-------+--------+---------+---------+--------+
| |零花钱 |解决问题| 当前支付| 下月预支|月底结余|
|月份 | | | | | |
+------+-------+--------+---------+---------+--------+
| 1 | 100 | 1, 2 | 40+60 | 0 | 0 |
| 2 | 100 | 3, 4 | 30+30 | 20+20 | 0 |
| 3 | 100 | -none- | 0 | 50+50 | 0 |
| 4 | 100 | 5 | 40 | 0 | 60 |
| 5 | 100 | -none- | 0 | 40 | 60 |
+------+-------+--------+---------+---------+--------+
//DP
program __solve;
var
a,b,suma,sumb:array[0..310] of longint;ans,n,m,i,j,x:longint;f:array[0..310,0..310] of longint;function min(a,b:longint):longint;
begin
if (a<b) then exit(a) else exit(b);end;
begin
assign(input,'solve.in');
reset(input);assign(output,'solve.out');rewrite(output);readln(m,n);for i:=1 to n dobegin
readln(a[i],b[i]);suma[i]:=suma[i-1]+a[i];sumb[i]:=sumb[i-1]+b[i];end;
fillchar(f,sizeof(f),63);f[0][1]:=0;for i:=1 to n dofor j:=1 to i dobegin
if (suma[i]-suma[i-j]>m) then break;if (sumb[i]-sumb[i-j]>m) then break;if (i=j) thenbegin
f[i][j]:=f[i-j][1]+2;continue;end;
for x:=1 to i-j dobegin
if (suma[i]-suma[i-j]<=m-sumb[i-j]+sumb[i-j-x]) thenf[i][j]:=min(f[i][j],f[i-j][x]+1);f[i][j]:=min(f[i][j],f[i-j][x]+2);end;
end;
ans:=maxlongint;for i:=1 to n doans:=min(ans,f[n][i]);writeln(ans);close(input);close(output);end.