#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
using namespace std;
int main()
{
int n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{
cout<<"+";
for(int i=0;i<n;++i)
{
cout<<"-";
}
cout<<"+"<<endl;
for(int i=0;i<m;++i)
{
cout<<"|";
for(int j=0;j<n;++j)
{
cout<<" ";
}
cout<<"|"<<endl;
}
cout<<"+";
for(int i=0;i<n;++i)
{
cout<<"-";
}
cout<<"+"<<endl;
cout<<endl;
}
return 0;
}
无题
#include<stdio.h>
#include<stdlib.h>
#include<iostream>
using namespace std;
struct ss
{
int num;
int ren;
int money;
}s[1001];
int c;
int cmp(const void *a,const void *b)
{
struct ss *c=(ss *)a;
struct ss *d=(ss *)b;
if(c->money-d->money)return c->money-d->money;
return d->ren-c->ren;
}
int find(int x)
{
int i;
for(i=0;i<c;i++)
{
if(s[i].ren>=x)
{
s[i].ren-=x;
return s[i].num;
}
}
return 0;
}
int main()
{
int t,n,i,x,ans;
scanf("%d",&t);
while(t--&&scanf("%d",&c))
{
for(i=0;i<c;i++)
{
scanf("%d %d %d",&s[i].num,&s[i].ren,&s[i].money);
}
qsort(s,c,sizeof(s[0]),cmp);
scanf("%d",&n);
while(n--&&scanf("%d",&x))
{
ans=find(x);
if(ans)
{
printf("%d\n",ans);
}
else
printf("sorry\n");
}
}
return 0;
}
推箱子
/*
思路:很简单的状态搜索题,大概就是对箱子采用BFS的思想,然后判断人是否可以走到箱子的对面(DFS/BFS),由于数据大,可以用四重标记数组来标记(hash[M][M][M][M])不过有许多细节需要注意。
(1)采用DFS/BFS判断人是否可以到达箱子的对面时,要明确人不能穿过箱子,即对箱子标记flag[p.Bx][p.By] = 1;
(2)求箱子的对面求坐标时要保证这个坐标没有超边界。
(3)DFS时不需要回溯。
(4)推箱子时,人的位置不会跟随箱子的移动而移动。
*/
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <queue>
using namespace std;
const int M = 8;
const int dx[] = {-1,1,0,0};
const int dy[] = {0,0,-1,1};
int maze[M][M];
int n, m;
int Bx, By, Mx, My;
int Nx, Ny;
int flag[M][M], hash[M][M][M][M];
int Found;
struct node
{
int Bx, By;
int Mx, My;
int step;
};
int check(int x, int y)
{
if(x >= 0 && x < n && y >= 0 && y < m && maze[x][y] != 1) return 1;
return 0;
}
void dfs(int Nx, int Ny, int Mx, int My)
{
if(Nx == Mx && Ny == My)
{
Found = 1;
return ;
}
for(int i = 0; i < 4 && !Found; i++)
{
int x = Nx + dx[i];
int y = Ny + dy[i];
if(check(x, y) && !flag[x][y])
{
flag[x][y] = 1;
dfs(x, y, Mx, My);
//flag[x][y] = 0; 只需要知道是否可以到达,而不需要回溯,否则TLE。
}
}
}
void bfs(int Bx, int By, int Mx, int My)
{
queue<node> Q;
node p, q;
p.Bx = Bx, p.By = By, p.Mx = Mx, p.My = My, p.step = 0;
Q.push(p);
while(!Q.empty())
{
p = Q.front(); Q.pop();
if(maze[p.Bx][p.By] == 3)
{
printf("%d\n", p.step);
return ;
}
for(int i = 0; i < 4; i++)
{
q = p;
q.Bx += dx[i];
q.By += dy[i];
Nx = p.Bx-dx[i];
Ny = p.By-dy[i]; //箱子对面的坐标
if(check(q.Bx, q.By)&& check(Nx, Ny) && !hash[q.Bx][q.By][Nx][Ny]) //check(Nx, Ny)
{
memset(flag, 0, sizeof(flag));
flag[p.Bx][p.By] = flag[Nx][Ny] = 1; //标记起点与箱子,确保人不能走过。
Found = 0;
dfs(Nx, Ny, p.Mx, p.My);
if(Found)
{
hash[q.Bx][q.By][Nx][Ny] = 1;
q.Mx = Nx, q.My = Ny;
q.step++;
Q.push(q);
}
}
}
}
printf("-1\n");
return ;
}
void init()
{
memset(hash, 0, sizeof(hash));
memset(maze, 0, sizeof(maze));
for(int i = 0; i < n; i++)
{
for(int j = 0; j < m; j++)
{
scanf("%d", &maze[i][j]);
if(maze[i][j] == 2)
{
Bx = i;
By = j;
}
if(maze[i][j] == 4)
{
Mx = i;
My = j;
}
}
}
}
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
scanf("%d%d", &n, &m);
init();
bfs(Bx, By, Mx, My);
}
return 0;
}
#define is unsafe
//数据结构-栈的应用
#include<iostream>
#include<string>
#include<vector>
using namespace std;
struct node
{
int value;//值
int add;//+的次数
};
//用容器实现栈的FILO
vector<node> ans;//数值栈
vector<char> sig;//符号栈
int main()
{
int t, i;
string str;
node temp, temp2;
cin>>t;
while(t--)
{
cin>>str;
temp.value = 0; temp.add = 0;
sig.clear(); ans.clear();
for(i = 0; i < str.length(); i++)
{
//逐字打扫,只有'('、'+'、 ','、')'和数字是有用的,"MAX"不用处理
//优先级:'(' > '+' > ',' > ')'
switch (str[i])
{
case '(':
sig.push_back(str[i]);
temp.value = 0; temp.add = 0;
break;
case '+':
ans.push_back(temp);
sig.push_back(str[i]);
temp.value = 0; temp.add = 0;
break;
case ',':
while(!sig.empty() && sig.back() == '+')
{
temp2 = ans.back();
temp.value = temp.value + temp2.value;
temp.add = temp.add + 1 + temp2.add;
ans.pop_back();
sig.pop_back();
}
ans.push_back(temp);
sig.push_back(str[i]);
temp.value = 0; temp.add = 0;
break;
case ')':
while(!sig.empty() && sig.back() == '+')
{
temp2 = ans.back();
temp.value = temp.value + temp2.value;
temp.add = temp.add + 1 + temp2.add;
ans.pop_back();
sig.pop_back();
}
temp2 = ans.back();
if(temp2.value > temp.value)
{
temp.value = temp2.value;
temp.add = temp2.add * 2 + temp.add;
}
else
{
temp.add = temp.add * 2 + temp2.add;
}
sig.pop_back();sig.pop_back();
ans.pop_back();
break;
case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9':
temp.value = temp.value * 10 + str[i] - '0';
break;
}
}
while(!sig.empty() && sig.back() == '+')
{
temp2 = ans.back();
temp.value = temp.value + temp2.value;
temp.add = temp.add + 1 + temp2.add;
ans.pop_back();
sig.pop_back();
}
cout<<temp.value<<' '<<temp.add<<endl;
}
return 0;
}
Exclusive-OR
/*
转自:http://www.cppblog.com/Yuan/archive/2010/09/02/125667.html?opt=admin稍许改写
有n(n<=20000)个未知的整数X0,X1,X2Xn-1,有以下Q个(Q<=40000)操作:
I p v :告诉你Xp=v
I p q v :告诉你Xp Xor Xq=v
Q k p1 p2 … pk : 询问 Xp1 Xor Xp2 .. Xor Xpk, k不大于15。
如果当前的I跟之前的有冲突的话,跳出
并查集扩展!
对于I p v ,如果虚设一个点Xn=0,则可以看成 I p n v (与0异或)
所以对于所有那些I,都是a^b=v,两个两个的,连带的效果
所以设val[i]=Xi^Xfa[i] 跟上面一样有连带效果 fa[i]为i的父亲
这样:
1) I p q v
先find
如果p q在同一集合,判断是否有Xp^Xq=v 不是的话矛盾
否则,合并 注意虚设的点n要始终保持为根
2)Q k p1pk
Xp1 ^ Xp2 ^ Xpk
转化为:
val[p1] ^ val[p2] ^ val[k] ^ (Xfa[p1] ^ Xfa[p2] ^ Xfa[pk])
val[pi]已知,只需判断Xfa[pi]是否已知
由于是异或,奇数个Xfa[pi]才需判断。判断方法为看他的根是不是Xn即可
*/
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int MAXN = 20010;
int fa[MAXN],val[MAXN];
int n,q;
void init(int n)
{
for(int i=0;i<=n;i++)
{
val[i]=0;
fa[i]=i;
}
}
int find(int a)
{
if(a!=fa[a])
{
int t=fa[a];
fa[a]=find(fa[a]);
val[a]^=val[t];
}
return fa[a];
}
bool unin(int a,int b,int v)
{
int ra=find(a);
int rb=find(b);
if(ra==rb)
{
return v==(val[a]^val[b]);
}
if(ra==n)swap(ra,rb);
fa[ra]=rb;
val[ra]=val[a]^val[b]^v;
return true;
}
char cmd[MAXN];
int main()
{
//freopen("in","r",stdin);
int t=1;
while(scanf("%d%d",&n,&q),n)
{
printf("Case %d:\n",t++);
init(n);
int fact = 0;
bool err = false;
for(int i=0;i<q;i++)
{
scanf(" %c",&cmd[0]);
if(err){gets(cmd);continue;}
if(cmd[0]=='I')
{
gets(cmd);//需要这样子
fact++;
int x,y,v;
if(sscanf(cmd,"%d%d%d",&x,&y,&v)==2)//sscanf() 直接scanf()会错不知为啥
{
swap(y,v);
y=n;
}
if(!unin(x,y,v))
{
err = true;
printf("The first %d facts are conflicting.\n",fact);
}
}
else
{
int k,x,ans=0,pos=-1,flag=true;
vector<pair<int,int> > V;
scanf("%d",&k);
for(int i=0,jj;i<k;i++)
{
scanf("%d",&x);
int rx=find(x);
rx=find(x);
ans^=val[x];
for(jj=0;jj<V.size();jj++)
{
if(V[jj].first==rx)break;
}
if(jj==V.size())V.push_back(make_pair(rx,1));
else V[jj].second++;
}
for(int j=0;j<V.size();j++)
{
if(V[j].second&1)
{
if(V[j].first!=n){flag=false;break;}
}
}
if(flag)printf("%d\n",ans);
else puts("I don't know.");
}
}
puts("");
}
return 0;
}
Stars
//二维树状数组
#include"stdio.h"
#include"string.h"
#include"stdlib.h"
#define N 1011
int m;
int C[N][N],hash[N][N];
int lowbit[1011];
void update(int y,int x,int dir)
{
int t;
while(0<y && y<=1001)
{
t=x;
while(0<t && t<=1001)
{
C[y][t]+=dir;
t+=lowbit[t];
}
y+=lowbit[y];
}
}
int sum(int y,int x)
{
int p=0;
int t;
while(0<y && y<=1001)
{
t=x;
while(0<t && t<=1001)
{
p+=C[y][t];
t-=lowbit[t];
}
y-=lowbit[y];
}
return p;
}
int main()
{
int i;
int x,y;
int a,b,c,d,x1,x2,y1,y2;
char str[20];
scanf("%d",&m);
memset(C,0,sizeof(C));
memset(hash,0,sizeof(hash));
for(i=1;i<=1005;i++) lowbit[i]=i&(-i);
while(m--)
{
scanf("%s",str);
if(str[0]=='B')
{
scanf("%d%d",&x,&y);
x++;y++;
if(hash[y][x]) continue;
update(y,x,1);
hash[y][x]=1;
}
else if(str[0]=='D')
{
scanf("%d%d",&x,&y);
x++;y++;
if(!hash[y][x]) continue;
update(y,x,-1);
hash[y][x]=0;
}
else if(str[0]=='Q')
{
scanf("%d%d%d%d",&a,&b,&c,&d);
x1=a>b?b:a;x2=a>b?a:b;
y1=c>d?d:c;y2=c>d?c:d;
x1++;x2++;y1++;y2++;
a=sum(y2,x2);
b=sum(y1-1,x1-1);
c=sum(y2,x1-1);
d=sum(y1-1,x2);
printf("%d\n",a-c-d+b);
}
}
return 0;
}
WuKong
/*
Dijkstra+记忆化搜索
首先用Dijkstra分别找到悟空和唐僧从起到终点的最短路径
最短路径的性质d[i] + edge[i][j] == d[j] 其中j为最短路径上的点,则i也为最短路径上的点。
由这个性质我们可以从终点逆向找到所有的最短路径上的点,做一遍记忆化搜索就可以得到结果。
*/
#include <iostream>
#include <memory.h>
#include <stdio.h>
using namespace std;
const int M = 320;
const int INF = 1 << 30;
int n,m;
int d[M][M],d1[M],d2[M],dp[M][M];
void INIT()
{
int u,v,w;
for(int i = 1;i <= n;i++)
{
for(int j = 1;j <= n;j++)
d[i][j] = INF;
}
for(int i = 0;i < m;i++)
{
scanf("%d%d%d",&u,&v,&w);
if(d[u][v] > w)
d[u][v] = d[v][u] = w;
}
memset(dp,-1,sizeof(dp));
return;
}
void Dijkstra(int s,int dist[])
{
int cover[M];
memset(cover,0,sizeof(cover));
for(int i = 1;i <= n;i++)
dist[i] = INF;
int temp,flag;
dist[s] = 0;
for(int i = 0;i < n;i++)
{
temp = INF;
for(int j = 1;j <= n;j++)
if(cover[j] == 0 && dist[j] < temp)
{
flag = j;
temp = dist[j];
}
cover[flag] = 1;
for(int j = 1;j <= n;j++)
if(cover[j] == 0 && d[flag][j] < INF && dist[j] > dist[flag] + d[flag][j])
dist[j] = dist[flag] + d[flag][j];
}
return;
}
int dfs(int a,int b)
{
if(dp[a][b] > -1)
return dp[a][b];
int i,j,v = 0;
/*if(a == b)
{
v++;
for(i = 1;i <= n;i++)
{
if(d1[i] + d[i][a] != d1[a])
continue;
for(j = 1;j <= n;j++)
if(d2[j] + d[j][b] == d2[b])
v = max(v,dfs(i,j)+1);
}
}*/
for(i = 1;i <= n;i++)
if(d1[i] + d[i][a] == d1[a])
v = max(v,dfs(i,b));
for(j = 1;j <= n;j++)
if(d2[j] + d[j][b] == d2[b])
v = max(v,dfs(a,j));
if(a==b)v++;
dp[a][b] = v;
return v;
}
int main()
{
while(cin >> n >> m && !(n == 0 && m == 0))
{
INIT();
int a,b,c,d;
scanf("%d%d%d%d",&a,&b,&c,&d);
dp[a][c] = 0;
if(a == c)
dp[a][c] = 1;
Dijkstra(a,d1);
Dijkstra(c,d2);
cout << dfs(b,d) << endl;
}
system("pause");
return 0;
}
A Very Simple Problem
/*
题意:给出N,x,M 要计算
N
∑(k^x)*(x^k) MOD M
k=1
x
用到二项式定理,(n+1)^x = ∑C(x,k)n^k
k=0
然后构造矩阵,求和 S(n)表示前n项和
*/
#include<cstdio>
#include<cstring>
long long C[55][55],A[55][55],start[55];
int M,N,x;
void init()
{
for(int i=0;i<=x;i++)C[i][0]=C[i][i]=1;
for(int i=2;i<=x;i++)
for(int j=1;j<i;j++)
{
C[i][j]=C[i-1][j]+C[i-1][j-1];
if(C[i][j]>=M)C[i][j]%=M;
}
//init A [0x+1][0x+1]
memset(A,0,sizeof(A));
for(int j=0;j<=x;j++)
for(int i=0;i<=j;i++)
{
A[i][j]=x*C[j][i];
if(A[i][j]>=M)A[i][j]%=M;
}
for(int i=0;i<=x;i++)
{
A[i][x+1]=x*C[x][i]%M;
if(A[i][x+1]>=M)A[i][x+1]%=M;
}
A[x+1][x+1]=1;
for(int j=0;j<=x+1;j++)start[j]=x;//N=1时
}
void mul(long long A[][55],long long B[][55])//A=A*B
{
long long R[55][55]={0};
for(int k=0;k<=x+1;k++)
for(int i=0;i<=x+1;i++)
if(A[i][k])
for(int j=0;j<=x+1;j++)
{
R[i][j]+=A[i][k]*B[k][j];
if(R[i][j]>=M)R[i][j]%=M;
}
for(int i=0;i<=x+1;i++)
for(int j=0;j<=x+1;j++)
A[i][j]=R[i][j];
}
void pow(long long m[][55],int n)//m=A^n
{
if(n==1)
{
for(int i=0;i<=x+1;i++)
for(int j=0;j<=x+1;j++)
m[i][j]=A[i][j];
return ;
}
pow(m,n/2);
mul(m,m);
if(n&1)mul(m,A);
}
int main()
{
//freopen("in","r",stdin);
while(scanf("%d%d%d",&N,&x,&M),N>0)
{
if(N==1){printf("%d\n",x%M);continue;}
init();
long long ans[55][55];
pow(ans,N-1);
long long res=0;
for(int i=0;i<=x+1;i++)
res+=start[i]*ans[i][x+1];
printf("%I64d\n",res%M);
}
return 0;
}