http://acm.zcmu.edu.cn/JudgeOnline/contest.php?cid=1086
签到
水
直接累加学号,再去掉来的,剩下的就是没有来的,注意数据范围较大使用long long
也可以使用异或操作,或者STL map或者set
#include<iostream> #include<cstdio> using namespace std; int n; int main() { while(~scanf("%d",&n)) { int ans,x; scanf("%d",&ans); for(int i=0;i<2*(n-1);i++)scanf("%d",&x),ans^=x; printf("%d\n",ans); } return 0; }
完美变换
数n每次有三种选择 n-1,n+2,n/3,n/3的下降到1的速度最快,用bfs 每次将可以用的选择加入队列,即可算出最小变换次数。bfs时,按照n/3 ,n-1 ,n-2的顺序放入队列。步数相同的层中,如果后面的数等于前面的数则舍弃后面的数。因为如果前面的数无解的话后面的数也无解;如果前面的数有解,那么后面的字典序会比前面的字典序大。
因为bfs过程中不可能有相同的数出现(否则舍弃第二次出现的相同数),所以直接用map记录前一个数就可以了
#include<iostream> #include<cstdio> #include<map> #include<queue> using namespace std; queue<pair<int,int> >q; map<int,int>pre; map<int,bool>vis; int n; void output(int val) { if(val==n){ printf("%d",n); return; } output(pre[val]); printf("->%d",val); } void bfs() { while(!q.empty())q.pop(); q.push(make_pair(n,0)); vis[n]=true; while(!q.empty()) { int val=q.front().first; int step=q.front().second; int tmp; q.pop(); if(val==1) { printf("%d ",step); output(val); puts(""); return; } tmp=val/3; if(val%3==0&&vis[tmp]==false) { q.push(make_pair(tmp,step+1)); pre[tmp]=val; vis[tmp]=true; } tmp=val-1; if(vis[tmp]==false) { q.push(make_pair(tmp,step+1)); pre[tmp]=val; vis[tmp]=true; } tmp=val+2; if(vis[tmp]==false) { q.push(make_pair(tmp,step+1)); pre[tmp]=val; vis[tmp]=true; } } } int main() { while(~scanf("%d",&n)) { vis.clear(); pre.clear(); bfs(); } return 0; }
愉快的玩耍 FZU2150
暴力乱搞
题意是在图上选择两个点(可以重合)进行搜索,最小的步数烧完所有草。
先用dfs检验数据,相邻的草算作一块,如果大于两块,则无解。
如果有解,则bfs。 如果选的是同一个点,则将一个点加入队列,如果选的是不同的点,则将两个点加入队列。
#include<iostream> #include<cstdio> #include<vector> #include<queue> #include<cstring> using namespace std; struct ss { int x,y; int step; }t; //l u r d int dx[4]={0,-1,0,1}; int dy[4]={-1,0,1,0}; int n,m; int cnt; char mp[20][20]; bool vis[20][20]; vector<pair<int,int> >v; queue<ss>q; void dfs(int x,int y) { vis[x][y]=true; for(int i=0;i<4;i++) { int xx=x+dx[i]; int yy=y+dy[i]; if(xx>=0&&xx<n&&yy>=0&&yy<m&&mp[xx][yy]=='#'&&!vis[xx][yy]) dfs(xx,yy); } } int bfs() { int num=0; while(!q.empty()) { ss p=q.front(); q.pop(); num++; if(num==cnt) { return p.step; } for(int i=0;i<4;i++) { t.x=p.x+dx[i]; t.y=p.y+dy[i]; t.step=p.step+1; if(t.x>=0&&t.x<n&&t.y>=0&&t.y<m&&mp[t.x][t.y]=='#'&&!vis[t.x][t.y]) { vis[t.x][t.y]=true; q.push(t); } } } return -1; } int main() { int T; scanf("%d",&T); for(int cas=1;cas<=T;cas++) { cnt=0; v.clear(); while(!q.empty())q.pop(); scanf("%d%d",&n,&m); for(int i=0;i<n;i++){ scanf("%s",mp[i]); for(int j=0;j<m;j++) { if(mp[i][j]=='#'){ v.push_back(make_pair(i,j)); } } } ///dfs检验数据,只要块大于2就无解 memset(vis,false,sizeof(vis)); int block=0; for(int i=0;i<n;i++) { for(int j=0;j<m;j++) { if(mp[i][j]=='#'&&!vis[i][j]) { dfs(i,j); block++; } } } if(block>2) { printf("Case %d: -1\n",cas); continue; } ///bfs cnt=v.size(); int mi=100000000; int tmp; for(int i=0;i<v.size();i++) { for(int j=i;j<v.size();j++) { memset(vis,false,sizeof(vis)); if(i==j) { while(!q.empty())q.pop(); t.x=v[i].first; t.y=v[i].second; t.step=0; q.push(t); vis[t.x][t.y]=true; tmp=bfs(); } else{ while(!q.empty())q.pop(); t.x=v[i].first; t.y=v[i].second; t.step=0; q.push(t); vis[t.x][t.y]=true; t.x=v[j].first; t.y=v[j].second; t.step=0; q.push(t); vis[t.x][t.y]=true; tmp=bfs(); } if(tmp==-1)continue; // printf("tmp=%d\n",tmp); mi=tmp<mi?tmp:mi; } } printf("Case %d: ",cas); if(mi==100000000)puts("-1"); else printf("%d\n",mi); } return 0; }
数牌
总共有52种牌面,用一个二维数组cnt[i][j]一次记录第j张 牌面为i 的牌的位置,用二分查找第k 张牌的位置。问题其实就是如何动态维护数组的有序性即 如 1 3 5 9 10 将5 改成11后数组依然要有序,可以用二维树状数组来维护,用二分查找找到第k张牌对应的位置。
提供一组测试数据
5
a3 a3 a3 a3 d2
4
1 1 5
2 1 a3
1 1 5
2 1 a3
树状数组保存牌的位置,数组维护的时间复杂度为mlog(n), 查询的时间复杂度为log(n), 所以总体时间复杂度为 mlog2(n)
#include<iostream> #include<cstdio> #include<vector> #include<cstring> #include<algorithm> using namespace std; #define low(x) x&(-x) #define maxn 100010 int n,m; int a[maxn]; int c[60][maxn]; void add(int k,int i,int val) { while(i<maxn) { c[k][i]+=val; i+=low(i); } } int getsum(int k,int i) { int sum=0; while(i>0) { sum+=c[k][i]; i-=low(i); } return sum; } int getnum(char *s) { int ans; ans=(s[0]-'a')*13; if(s[1]>='3'&&s[1]<='9')ans+=s[1]-'0'-2; else if(s[1]=='1'&&s[2]=='0')ans+=8; else if(s[1]=='J')ans+=9; else if(s[1]=='Q')ans+=10; else if(s[1]=='K')ans+=11; else if(s[1]=='A')ans+=12; else if(s[1]=='2')ans+=13; return ans; } int binarysearch(int k,int x) { int l=0,r=maxn-1; while(l<r) { int mid=(l+r)>>1; if(getsum(k,mid)>=x)r=mid; else l=mid+1; } return r; } int main() { // freopen("test.in","r",stdin); // freopen("test.out","w",stdout); while(~scanf("%d",&n)) { char str[5]; memset(c,0,sizeof(c)); for(int i=1;i<=n;i++) { scanf("%s",str); a[i]=getnum(str); add(a[i],i,1); } scanf("%d",&m); int op; while(m--) { scanf("%d",&op); if(op==1) { int x,y; scanf("%d%d",&x,&y); if(a[x]==a[y])continue; add(a[x],x,-1); add(a[x],y,1); add(a[y],y,-1); add(a[y],x,1); a[x]^=a[y]^=a[x]^=a[y]; } else { int num,k,sum; scanf("%d%s",&num,str); k=getnum(str); sum=getsum(k,maxn); if(num>sum)puts("-1"); else printf("%d\n",binarysearch(k,num)); } } } return 0; }
组合数
lucas定理:Lucas(n,m,p)=c(n%p,m%p)*Lucas(n/p,m/p,p) ,p为素数。数据水
#include<iostream> #include<cstdio> using namespace std; int n,m,mod; int c(int n,int m) { if(n<m)return 0; int ans=1; int i=n,j=1; while(j<=m) { ans=ans*i/j; i--; j++; } return ans%mod; } int main() { int T; scanf("%d",&T); while(T--) { scanf("%d%d%d",&n,&m,&mod); int ans=1; while(n&&m) { ans=(ans*c(n%mod,m%mod))%mod; n/=mod; m/=mod; } printf("%d\n",ans); } return 0; }
浙公网安备 33010602011771号