@Asuna
2017-04-14T17:53:20.000000Z
字数 4460
阅读 973
题解
题意:求某个点到各点的代价,两点间某条路径的代价定义为路径上权值最大的边的权值,而两点间的权值表示为它们之间所有路径代价的最小值。
题解:dist[u]表示从原点到点u的路径的代价,用Dijkstra。最后注意判断重边。
参考代码:
#include<iostream>#include<cstring>#include<cstdio>#include<cmath>#include<cstdlib>#include<vector>#include<queue>using namespace std;typedef pair <int, int> p;int dist[510];priority_queue < p, vector<p>, greater<p> > qu;struct node{int nxt;int w;int to;}edge[40000];bool vis[510];int head[510],tot;void addedge(int from, int to, int w){edge[tot].to=to;edge[tot].w=w;edge[tot].nxt=head[from];head[from]=tot++;}void Dijkstra(int u, int n){while (!qu.empty()){qu.pop();}for (int i=0; i<n; i++){dist[i]=100000000;}dist[u]=0;qu.push(make_pair(dist[u], u));while (!qu.empty()){p tmp=qu.top();qu.pop();int s=tmp.second;int d=tmp.first;for (int i=head[s]; ~i; i=edge[i].nxt){int t=edge[i].to;int w=edge[i].w;if (dist[t]>max(d, w)){dist[t]=max(d, w);qu.push(make_pair(dist[t], t));}}}}int main() {int t, icase=1;scanf("%d", &t);while (t--){int n, m;scanf("%d%d", &n, &m);for (int i=0; i<n; i++){head[i]=-1;}tot=0;int u, v, w;for (int i=1; i<=m; i++){scanf("%d%d%d", &u, &v, &w);addedge(u, v, w);addedge(v, u, w);}scanf("%d", &u);Dijkstra(u, n);printf("Case %d:\n", icase++);for (int i=0; i<n; i++){if (dist[i]==100000000){printf("Impossible\n");}else{printf("%d\n", dist[i]);}}}return 0;}
题意:给定两个数a,b,求a到b所有数的0的个数。
题解:dp[位数][0~9][0的个数]; 然后记忆化搜索的时候 dfs(第几位,前面有没有非0的数,取数的限制,0的个数);
参考代码:
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;long long n, m;long long cal(long long x){if (x<0) return 0;long long ans=1, cnt=1, tmp=0;while (x>=10){long long cur=x%10;x/=10;if (cur!=0) ans+=x*cnt;else ans+=(x-1)*cnt+tmp+1;tmp+=cur*cnt;cnt*=10;}return ans;}int main(){int t,icase=1;cin>>t;while(t--){scanf("%d%d",&n,&m);printf("Case %d: %lld\n", icase++,cal(m)-cal(n-1));}return 0;}
题意:求(1^K + 2^K + 3^K + ... + N^K)%2^32
题解:矩阵快速幂,由于不知道怎么搞数学公式在这个上面。。。找了篇网上写的比较详细的题解。。http://blog.csdn.net/kg20006/article/details/51057305需要注意的就是转移矩阵还有mod 2^32可以用自然溢出完成。
ps:似乎是伯努利数?有兴趣可以baidu一下伯努利数的相关题目,似乎还蛮多的好像也有点用但是我看不怎么懂。。。。
参考代码:
#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>using namespace std;const long long mod=((long long)1<<32);long long k,siz,n,C[60][60];struct Matrix{long long a[53][53];Matrix(){memset(a, 0, sizeof(a));for(int i=1; i<=52; i++){a[i][i]=1;}}};Matrix operator * (const Matrix & m1, const Matrix & m2){Matrix m;for(int i=1; i<=siz; i++){for(int j=1; j<=siz; j++){m.a[i][j]=0;for(int k=1; k<=siz; k++){m.a[i][j]=(m.a[i][j]+(m1.a[i][k]*m2.a[k][j])%mod)%mod;}}}return m;}Matrix quick_pow(Matrix base, long long pow){Matrix A;while(pow){if(pow&1){A=A*base;}base=base*base;pow>>=1;}return A;}int main(){long long t;memset(C,0,sizeof(C));C[0][0]=1;C[1][0]=C[1][1]=1;for(int i=2; i<=50; i++){for(int j=0; j<=i; j++){if (j==0){C[i][j]=1;}else{C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;}}}scanf("%lld",&t);for (long long cas=1; cas<=t; cas++){scanf("%lld%lld",&n,&k);siz=k+2;Matrix tran;memset(tran.a, 0, sizeof(tran.a));for(int i=1; i<=k+1; i++){for(int j=1; j<=k+1; j++){if(i<=j){tran.a[i][j]=C[k+1-i][j-i];}}}for(int i=1; i<=k+1; i++){tran.a[k+2][i]=C[k][i-1];}tran.a[k+2][k+2]=1;Matrix ans=quick_pow(tran,n-1);long long ans1=0;for(int i=1; i<=k+2; i++){ans1=(ans1+ans.a[k+2][i])%mod;}printf("Case %lld: %lld\n",cas,ans1);}return 0;}
题意:给一个动态的序列,每次询问序列中第k个元素是啥,询问完以后,就删除这个元素,同时可以在结尾添加元素,如果当前位置没有元素,就输出“none”。
题解:区间修改+区间询问+单点修改的线段树。一开始毫无头绪,好在mzjj和js提示了许多。。总的来说树上维护的东西是当前区间内还有多少个元素没被删除,这样当询问到某一棵子树的时候,如果左子树的元素个数大于k,那么元素必定在左子树当中,否则就在右子树当中,在左子树当中固然好,就是左子树区间内第k个,在右子树的话就应该是第k减去左子树元素个数个,同时在叶子结点维护元素值。
参考代码:
#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<algorithm>using namespace std;int num[800010],id[800010],ans;void pushup(int rt){num[rt]=num[rt*2]+num[rt*2+1];}void build(int l,int r,int rt){num[rt]=0;id[rt]=-1;if (l==r) return;int mid=(l+r)/2;build(l,mid,rt*2);build(mid+1,r,rt*2+1);}void update(int x,int c,int l,int r,int rt){if (l==r){num[rt]=1;id[rt]=c;return;}int mid=(l+r)/2;if (x<=mid) update(x,c,l,mid,rt*2);else update(x,c,mid+1,r,rt*2+1);pushup(rt);}void query(int k, int l, int r, int rt){num[rt]-=1;if (l==r){ans=id[rt];id[rt]=-1;return;}int mid=(l+r)/2;if (num[rt*2]>=k) query(k,l,mid,rt*2);else{k-=num[rt*2];query(k,mid+1,r,rt*2+1);}}int main(){int t,icase=1;;scanf("%d",&t);while(t--){int n,m,sum;scanf("%d%d",&n,&m);sum=n+m;build(1,sum,1);printf("Case %d:\n",icase++);for (int i=1; i<=n; i++){int x;scanf("%d",&x);update(i,x,1,sum,1);}while (m--){char s[2];int x;scanf("%s%d",s,&x);if (s[0]=='a'){n+=1;update(n,x,1,sum,1);}else{query(x,1,sum,1);if (ans==-1) printf("none\n");else printf("%d\n",ans);}}}return 0;}