2016"百度之星" - 初赛(Astar Round2A)
Posted Meek
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2016"百度之星" - 初赛(Astar Round2A)相关的知识,希望对你有一定的参考价值。
题目链接:
http://bestcoder.hdu.edu.cn/contests/contest_show.php?cid=701
1001 :
矩阵快速幂
#include <iostream> #include <algorithm> #include <cstdio> #include <cstring> #include <cmath> #include<queue> #include<vector> using namespace std; const int N = 5e5+20, M = 1e2+10, mod = 1000000007,inf = 1e9; typedef long long ll; struct Matix { ll arr[M][M]; }; ll x,m,k,c; Matix mul(Matix a,Matix b,ll hang ,ll lie) { Matix ans; memset(ans.arr,0,sizeof(ans.arr)); for(int i=1;i<=hang;i++) { for(int t=1;t<=lie;t++) for(int j=1;j<=lie;j++) { ans.arr[i][t]+=(a.arr[i][j]*b.arr[j][t]); ans.arr[i][t]%=k; } } return ans; } Matix pow(Matix ans,Matix a,ll x) { while(x) { if(x&1) ans=mul(ans,a,2,2); a=mul(a,a,2,2); x/=2; } return ans; } int main(){ ll x,y,z; int T,cas=1; scanf("%d",&T); while(T--) { scanf("%I64d%I64d%I64d%I64d",&x,&m,&k,&c); Matix fir,sec; Matix now; now.arr[1][1]=x; now.arr[1][2]=x; memset(fir.arr,0,sizeof(fir.arr)); sec.arr[1][1]=10;sec.arr[1][2]=0; sec.arr[2][1]=1;sec.arr[2][2]=1; fir.arr[1][1]=1; fir.arr[2][2]=1; fir=pow(fir,sec,m-1);fir=mul(now,fir,2,2); printf("Case #%d:\\n",cas++); if(fir.arr[1][1]==c)puts("Yes"); else puts("No"); } return 0; }
1002:
状态压缩DP
我们设定dp[1<<16][16]:dp[i][j]:i为当前选取的状态并以第j个数结尾的最大值,那么答案就是 max{dp[全集][k]} k属于0到n-1
对于dp[i][j] , i这个状态已经填了x个数,我们准备填第x+1个数时, 如果当前x+1位置必填某个数,那么 就只更新以规定的这个数结尾转移方程
如果没有那就 枚举那么可以任意放的数来更新相应的状态及答案
#include <iostream> #include <algorithm> #include <cstdio> #include <cstring> #include <cmath> #include<queue> #include<vector> using namespace std; const int N = 1<<17, M = 1e6+10, mod = 1000000007,inf = 1e9; typedef long long ll; ll dp[1<<17][17]; int n,a[N],p[N],H[N],F[N]; int main() { int T,cas = 1; scanf("%d",&T); while(T--) { scanf("%d",&n); memset(H,0,sizeof(H)); memset(F,-1,sizeof(F)); int tmp = 0; for(int i=0;i<n;i++) { scanf("%d%d",&a[i],&p[i]); if(p[i]!=-1) H[i] = 1,F[p[i]] = i; } for(int i=0;i<(1<<n);i++) for(int j=0;j<n;j++) dp[i][j] = -1e18; // for(int i=0;i<n;i++) // for(int j=0;j<n;j++) if(i!=j&&!H[i]&&!H[j]) dp[(1<<i)|(1<<j)][j] = a[i]*a[j], dp[(1<<i)|(1<<j)][i] = a[i]*a[j]; if(F[0]!=-1) dp[(1<<F[0])][F[0]] = 0; else { for(int i=0;i<n;i++) { if(!H[i]) dp[(1<<i)][i] = 0; } } int U = (1<<n) - 1; for(int i=1;i<=U;i++) { int counts = 0; for(int j=0;j<n;j++) if((1<<j)&(i)) counts++; if(F[counts]!=-1) { counts = F[counts]; for(int j=0;j<n;j++) if(i&(1<<j)&&counts!=j)dp[i|(1<<(counts))][counts] = max(dp[i][j]+a[j]*a[counts],dp[i|(1<<counts)][counts]); } else { for(int k=0;k<n;k++) { if((1<<k)&(i)) for(int j=0;j<n;j++) { if(!((1<<j)&i)) { dp[i|(1<<j)][j] = max(dp[i|(1<<j)][j],dp[i][k]+a[k]*a[j]); } } } } } printf("Case #%d:\\n",cas++); ll ans = -1e18; for(int i=0;i<n;i++) ans = max(dp[U][i],ans) ; printf("%I64d\\n",ans); } return 0; }
1004:D Game
区间dp
设定dp[i][j]为i到j这个区间的最大答案,每次去选择连续不连续的2个/3个去删除,暴力转移就好
#include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include <algorithm> #include<map> using namespace std; const int N = 315, M = 30005, mod = 1e9 + 7, inf = 0x3f3f3f3f; typedef long long ll; int dp[N][N]; ll a[N],d; map<ll,int > mp; int dfs(int l,int r) { if(dp[l][r]!=-1) return dp[l][r]; int& ret = dp[l][r]; ret = 0; if(l>=r) return ret; if(l+1==r) { if(mp[a[r]-a[l]]) return (ret = 2); else return (ret = 0); } int tmp = 0; if(mp[a[r]-a[l]]) tmp+=2;// cout<<a[r]-a[l]<<endl; if(dfs(l+1,r-1)==((r-1)-(l+1)+1)) ret = tmp+((r-1)-(l+1)+1); if(abs(a[r]-a[l])%2==0&&mp[(a[r]-a[l])/2]) for(int i=l+1;i<r;i++) { tmp = 0; if(a[r]-a[i]==a[i]-a[l]&&mp[a[i]-a[l]]) { tmp = 3; } else continue; if(tmp+dfs(l+1,i-1)+dfs(i+1,r-1)==r-l+1) { ret = r-l+1;break; } } for(int i=l+1;i<r;i++) { ret = max(ret,dfs(l,i)+dfs(i+1,r)); } return ret; } int main() { int T,m,n; scanf("%d",&T); while(T--) { mp.clear(); memset(dp,-1,sizeof(dp)); scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%I64d",&a[i]); for(int i=1;i<=m;i++) scanf("%I64d",&d),mp[d] = 1; printf("%d\\n",dfs(1,n)); } return 0; } /* 1 7 2 1 5 8 101 59 62 201 100 3 */
1005:
预处理+dfs
预处理每种长度,每种长度的答案
再对对应长度dfs求出答案
#include <iostream> #include <algorithm> #include <cstdio> #include <cstring> #include <cmath> #include<queue> #include<vector> using namespace std; const int N = 1e3+20, M = 1e6+10, mod = 1000000007,inf = 1e9; typedef long long ll; ll len[N],dp[N],L,R; ll dfs(ll x){ if(x<=0) return 0; if(x<=2) return x; if(x==3) return 2; ll ans=0; int pos = upper_bound(len+1,len+62,x) - len - 1; if(len[pos]==x) return dp[pos]; if(x-len[pos]==1) return dp[pos]+1; ll ret = dp[pos]+1; ll shen = x-len[pos]-1; return ret+shen - dp[pos] + dfs(len[pos] - shen); } int main() { dp[1] = 1; len[1] = 1; for(int i=2;i<=61;i++) { len[i] = len[i-1]*2+1; } for(int i=2;i<=61;i++) { dp[i] = dp[i-1] + 1 + len[i-1] - dp[i-1]; } int T; scanf("%d",&T); while(T--) { scanf("%I64d%I64d",&L,&R); printf("%I64d\\n",dfs(R)-dfs(L-1)); } return 0; }
1006
优先队列
首先按照拓扑,将入度为0的压入,优先位置大的放前面。。。
#include <iostream> #include <algorithm> #include <cstdio> #include <cstring> #include <cmath> #include<queue> #include<vector> using namespace std; const int N = 5e5+20, M = 1e6+10, mod = 1000000007,inf = 1e9; typedef long long ll; int k,c,x,d[N],n,m,vis[N]; vector<int >G[N]; int ans[N]; int main() { int T; int cas = 1; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) G[i].clear(); for(int i=1;i<=n;i++) vis[i] = 0,d[i] = 0; for(int i=1;i<=m;i++) { int a,b; scanf("%d%d",&a,&b); G[a].push_back(b); d[b]++; } priority_queue<int > q; for(int i=1;i<=n;i++) { if(d[i]==0) q.push(i); } int cnt =0 ; while(!q.empty()) { int k = q.top(); ans[++cnt] = k; // cout<<k<<endl; q.pop(); for(int i=0;i<G[k].size();i++) { d[G[k][i]]--; if(d[G[k][i]]==0&&!vis[G[k][i]]) { q.push(G[k][i]); vis[G[k][i]] = 1; } } } int mi = 1e9; ll aa = 0; for(int i=1;i<=cnt;i++) { mi = min(ans[i],mi); aa = aa + mi; } printf("%I64d\\n",aa); } return 0; }
以上是关于2016"百度之星" - 初赛(Astar Round2A)的主要内容,如果未能解决你的问题,请参考以下文章
2016"百度之星" - 初赛(Astar Round2B)
2016"百度之星" - 初赛(Astar Round2A)
2016"百度之星" - 初赛(Astar Round2B)
2016"百度之星" - 初赛(Astar Round2A)