此处有目录↑
http://acm.hdu.edu.cn/showproblem.php?pid=5650
1 3 1 2 3
0 In the sample,S = {1, 2, 3}, subsets of S are: Φ, {1}, {2}, {3}, {1, 2}, {1, 3}, {2, 3}, {1, 2, 3}
题目大意:记f(s)为s集合中所有元素的异或,给定一个集合S,求所有f(s)的异或,s⊆S。
做的时候没有仔细分析,想了个错误的解法(n为奇数时输出所有元素的异或,否则输出0),竟然水过了,原来数据这么水...
官方题解:
设集合有n个数,则包含x的子集个数有2^(n-1)个。 那么当n > 1时,x出现了偶数次,所以其对答案的贡献就是0;当 n = 1时,其对答案的贡献是 x。
#include <cstdio> using namespace std; int T,n; long long ans,tmp; int main() { scanf("%d",&T); while(T--) { scanf("%d",&n); ans=0; for(int i=0;i<n;++i) { scanf("%I64d",&tmp); ans^=tmp; } printf("%I64d\n",(n==1)?ans:0); } return 0; }
http://acm.hdu.edu.cn/showproblem.php?pid=5651
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
3 aa aabb a
1 2 1
题目大意:给定一行小写字母组成的字符串,求能形成多少个回文串?
若出现奇数次的字母的个数大于1,则无法组成回文串
否则只考虑左半边的情况,答案为左半边的排列数
写到一半,换了个变量名,导致初始化错误,查错半天...
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; int T,len,cnt[127],tol,t,gcd,num[505],nn,deno[505],nd; long long ans; char s[1005]; const long long mod=1000000007; int main() { scanf("%d",&T); while(T--) { memset(cnt,0,sizeof(cnt)); scanf("%s",s); len=strlen(s); for(int i=0;i<len;++i) ++cnt[s[i]]; tol=0; for(int i='a';i<='z';++i) if((cnt[i]&1)==1) { ++tol; --cnt[i]; } if(tol>1) { printf("0\n"); continue; } nn=len>>1; for(int i=0;i<nn;++i) num[i]=i+1; for(int i='a';i<='z';++i) {//枚举每个字母 for(int j=cnt[i]>>1;j>1;--j) { t=j; for(int k=0;k<nn&&t>1;++k) {//分子约去分母 gcd=__gcd(num[k],t); if(gcd>1) { num[k]/=gcd; t/=gcd; } } } } ans=1; for(int i=0;i<nn;++i) ans=(ans*num[i])%mod; printf("%I64d\n",ans); } return 0; }
————————————————————2题的旅游分割线————————————————————
http://acm.hdu.edu.cn/showproblem.php?pid=5652
1 4 6 011010 000010 100001 001000 7 0 3 1 5 1 3 0 0 1 2 2 4 2 1
4
题目大意:给一个n*m的01地图(0代表能走,1代表不能走),和q个操作,第i个操作令(x,y)处为1,判断多少个操作后无法从最上面走到最下面(只能向相邻的四个方向走)。
转换成判断1是否能从最左边到达最右边时出错,判断'0'时只用判断四个方向,而判断'1'时必须判断8个方向,一直没想到,比赛时没调出来...
#include <cstdio> #include <cstring> #include <queue> #include <algorithm> using namespace std; struct Node { int x,y; Node(int xx=0,int yy=0):x(xx),y(yy) {} }u; int T,n,m,num,x[250005],y[250005]; char ori[505][505],cur[505][505]; bool vis[505][505]; queue<Node> q; const int dx[8]={-1,-1,0,1,1,1,0,-1}; const int dy[8]={0,1,1,1,0,-1,-1,-1}; inline bool isInside(int xx,int yy) { return 0<=xx&&xx<n&&0<=yy&&yy<m; } bool bfs(int cc) { for(int i=0;i<n;++i) { for(int j=0;j<m;++j) { cur[i][j]=ori[i][j]; vis[i][j]=false; } } for(int i=1;i<=cc;++i) cur[x[i]][y[i]]='1'; while(!q.empty()) q.pop(); int xx,yy; for(xx=0;xx<n;++xx) {//左起的山 if(cur[xx][0]=='1') { vis[xx][0]=true; q.push(Node(xx,0)); } } while(!q.empty()) { u=q.front(); q.pop(); for(int i=0;i<8;++i) { xx=u.x+dx[i]; yy=u.y+dy[i]; if(isInside(xx,yy)&&!vis[xx][yy]&&cur[xx][yy]=='1') { if(yy==m-1)//若能到达右边则不连通 return true; vis[xx][yy]=true; q.push(Node(xx,yy)); } } } return false; } int main() { scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); for(int i=0;i<n;++i) scanf("%s",ori[i]); scanf("%d",&num); for(int i=1;i<=num;++i) scanf("%d%d",x+i,y+i); if(bfs(0)) { printf("0\n"); continue; } int l=1,r=num+1,mid; while(l<=r) { mid=(l+r)>>1; if(bfs(mid)) r=mid-1; else l=mid+1; } printf("%d\n",l>num?-1:l); } return 0; }
#include <cstdio> #include <cstring> using namespace std; int T,n,m,num,x[250005],y[250005]; int par[250005],u,xx,yy; char ori[505][505]; const int sta=250002,des=250003; const int dx[4]={-1,0,1,0}; const int dy[4]={0,1,0,-1}; inline bool isInside(int xx,int yy) { return 0<=xx&&xx<n&&0<=yy&&yy<m; } inline int cal(int x,int y) { if(x==-1) return sta; if(x==n) return des; return x*m+y; } int getPar(int a) { if(a==par[a]) return a; return par[a]=getPar(par[a]); } inline void merg(int a,int b) { int pa=getPar(a),pb=getPar(b); if(pa!=pb) par[pa]=pb; } int main() { scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); for(int i=0;i<n;++i) scanf("%s",ori[i]); scanf("%d",&num); for(int i=1;i<=num;++i) { scanf("%d%d",x+i,y+i); ori[x[i]][y[i]]='1'; } par[sta]=sta; par[des]=des; for(int i=0;i<n;++i) {//初始化每个点与自己联通 for(int j=0;j<m;++j) { u=cal(i,j); par[u]=u; } } for(int i=0;i<n;++i) { for(int j=0;j<m;++j) { if(ori[i][j]=='0') { u=cal(i,j); for(int dir=0;dir<4;++dir) { xx=i+dx[dir]; yy=j+dy[dir]; if(xx==-1||xx==n||(isInside(xx,yy)&&ori[xx][yy]=='0')) merg(u,cal(xx,yy)); } } } } if(getPar(sta)==getPar(des)) { printf("-1\n"); continue; } while(num>0) { ori[x[num]][y[num]]='0'; u=cal(x[num],y[num]); for(int dir=0;dir<4;++dir) { xx=x[num]+dx[dir]; yy=y[num]+dy[dir]; if(xx==-1||xx==n||(isInside(xx,yy)&&ori[xx][yy]=='0')) merg(u,cal(xx,yy)); } if(getPar(sta)==getPar(des)) break; --num; } printf("%d\n",num); } return 0; }