2016"百度之星" - 初赛(Astar Round2A)题解
来源:互联网 发布:淘宝9月份活动 编辑:程序博客网 时间:2024/05/22 11:04
今天是一年一度的百度之星初赛的日子啊,大家都早早的准备好了比(上)赛(分),运气也不错,涨了不少分,rating到了2222(真尼玛2)
ps.我是开黑做的,所以这分数不代表真实水平,勿黑
1001
给你一个由m个x组成的数字,模上k,问你是否等于c
k和c都小于10000,所以可以模拟,因为循环节不会大于10000,但是模拟很容易错,因为找到循环节的地方需要扣掉前面一段,然后各种XJB搞
模拟代码:
#include <map>#include <set>#include <stack>#include <queue>#include <cmath>#include <string>#include <vector>#include <cstdio>#include <cctype>#include <cstring>#include <sstream>#include <cstdlib>#include <iostream>#include <algorithm>#pragma comment(linker, "/STACK:102400000,102400000")using namespace std;#define MAX 100005#define MAXN 6005#define maxnode 15#define sigma_size 30#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1#define lrt rt<<1#define rrt rt<<1|1#define middle int m=(r+l)>>1#define LL long long#define ull unsigned long long#define mem(x,v) memset(x,v,sizeof(x))#define lowbit(x) (x&-x)#define pii pair<int,int>#define bits(a) __builtin_popcount(a)#define mk make_pair#define limit 10000//const int prime = 999983;const int INF = 0x3f3f3f3f;const LL INFF = 0x3f3f;const double pi = acos(-1.0);//const double inf = 1e18;const double eps = 1e-8;const LL mod = 1e9+7;const ull mx = 133333331;/*****************************************************/inline void RI(int &x) { char c; while((c=getchar())<'0' || c>'9'); x=c-'0'; while((c=getchar())>='0' && c<='9') x=(x<<3)+(x<<1)+c-'0'; }/*****************************************************/int vis[10005];int main(){ int t,kase=0; cin>>t; while(t--){ int x; LL m; int k,c; cin>>x>>m>>k>>c; int mo=0; mem(vis,0); int xun=INF; int tmp; for(int i=1;i<=m;i++){ mo=(mo*10+x)%k; if(vis[mo]){ xun=i-vis[mo]; tmp=vis[mo]; break; } vis[mo]=i; } kase++; printf("Case #%d:\n",kase); if(xun==INF){ if(mo!=c) printf("No\n"); else printf("Yes\n"); } else{ m=(m-tmp)%xun; int mm=mo; for(int i=0;i<m;i++){ mm=(mm*10+x)%k; } if(mm!=c) printf("No\n"); else printf("Yes\n"); } } return 0;}
但是这题还有一种更加美妙的姿势,就是
ps.还有人说可以用矩阵快速幂搞,貌似也是可以的呢
1002
题意是给你n个数字,然后有些数字的位置已经固定,还有些数字的位置没有固定,让你给n个数字安排位置,使得相邻的数字的乘积和最大,有负数
首先需要记录,每个位置上是否有要求必须放第几个数
n最大范围是16,所以应该是状压,但是比赛时候我并不知道怎么dp,TAT
先确定状态
(这个状态挺巧妙的感觉,我承认我确实没有想到,状压dp还是太渣了)
这样的话状态转移就很简单了辣
假设i的二进制表示里面有x个1,那么要保证第x个位置上必须要放k或者是没有要求,否则不能转移。
代码:
#include <map>#include <set>#include <stack>#include <queue>#include <cmath>#include <string>#include <vector>#include <cstdio>#include <cctype>#include <cstring>#include <sstream>#include <cstdlib>#include <iostream>#include <algorithm>#pragma comment(linker, "/STACK:102400000,102400000")using namespace std;#define MAX 100005#define MAXN 6005#define maxnode 15#define sigma_size 30#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1#define lrt rt<<1#define rrt rt<<1|1#define middle int m=(r+l)>>1#define LL long long#define ull unsigned long long#define mem(x,v) memset(x,v,sizeof(x))#define lowbit(x) (x&-x)#define pii pair<int,int>#define bits(a) __builtin_popcount(a)#define mk make_pair#define limit 10000//const int prime = 999983;const int INF = 0x3f3f3f3f;const LL INFF = 0x3f3f;const double pi = acos(-1.0);//const double inf = 1e18;const double eps = 1e-8;const LL mod = 1e9+7;const ull mx = 133333331;/*****************************************************/inline void RI(int &x) { char c; while((c=getchar())<'0' || c>'9'); x=c-'0'; while((c=getchar())>='0' && c<='9') x=(x<<3)+(x<<1)+c-'0'; }/*****************************************************/LL dp[1<<18][20];int a[20];int b[20];int main(){ int t,kase=0; cin>>t; while(t--){ int n; cin>>n; mem(b,-1); 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++){ int p; scanf("%d%d",&a[i],&p); if(p!=-1) b[p]=i; } if(b[0]!=-1) dp[(1<<b[0])][b[0]]=0; else for(int i=0;i<n;i++) dp[(1<<i)][i]=0; for(int i=1;i<(1<<n);i++){ for(int j=0;j<n;j++){ if(i&(1<<j)){ for(int k=0;k<n;k++){ if((i&(1<<k))==0){ int pos=bits(i); if(b[pos]==k||b[pos]==-1){ dp[i|(1<<k)][k]=max(dp[i|(1<<k)][k],dp[i][j]+a[j]*a[k]); } } } } } } LL maxn=-1e18; for(int i=0;i<n;i++){ maxn=max(maxn,dp[(1<<n)-1][i]); } kase++; printf("Case #%d:\n",kase); cout<<maxn<<endl; } return 0;}
1003
这是一道很不错的树上的题目,给你n个点的树,然后每个点有权值,有两种操作,一种是把某个点的权值修改,另一种是求一条从0开始必须经过x点的路径,使得路径上的点权和最大
因为要至少走到x,甚至要走到x的子树上,所以我们考虑可以用dfs序来解这题,因为dfs序的特性,我们维护每个点到0点的距离,这样就能很快用线段树求出在x的子树上的一点,它到0点的权值和最大
因为点权有负数,所以我们dfs的时候,dfs序只能在进入的时候++,出来的时候就不要++了,这样可以去掉很多0的节点(我的dfs序还是很弱啊,本来准备复习下,结果比赛就考了)
有了dfs序和线段树就很容易辣呀,这样就更新的时候区间加和
代码:
#include <map>#include <set>#include <stack>#include <queue>#include <cmath>#include <string>#include <vector>#include <cstdio>#include <cctype>#include <cstring>#include <sstream>#include <cstdlib>#include <iostream>#include <algorithm>#pragma comment(linker, "/STACK:102400000,102400000")using namespace std;#define MAX 100005#define MAXN 6005#define maxnode 15#define sigma_size 30#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1#define lrt rt<<1#define rrt rt<<1|1#define middle int m=(r+l)>>1#define LL long long#define ull unsigned long long#define mem(x,v) memset(x,v,sizeof(x))#define lowbit(x) (x&-x)#define pii pair<int,int>#define bits(a) __builtin_popcount(a)#define mk make_pair#define limit 10000//const int prime = 999983;const int INF = 0x3f3f3f3f;const LL INFF = 0x3f3f;const double pi = acos(-1.0);//const double inf = 1e18;const double eps = 1e-8;const LL mod = 1e9+7;const ull mx = 133333331;/*****************************************************/inline void RI(int &x) { char c; while((c=getchar())<'0' || c>'9'); x=c-'0'; while((c=getchar())>='0' && c<='9') x=(x<<3)+(x<<1)+c-'0'; }/*****************************************************/struct Edge{ int v,next;}edge[MAX*2];int head[MAX];int tot;int a[MAX];int ti;int p1[MAX];int p2[MAX];LL val[MAX];void init(){ mem(head,-1); mem(val,0); tot=0; ti=0;}void add_edge(int a,int b){ edge[tot].v=b; edge[tot].next=head[a]; head[a]=tot++;}LL sum[MAX<<2];LL col[MAX<<2];void pushup(int rt){ sum[rt]=max(sum[lrt],sum[rrt]);}void build(int l,int r,int rt){ col[rt]=0; if(l==r){ sum[rt]=val[l]; return; } middle; build(lson); build(rson); pushup(rt);}void pushdown(int rt,int m){ if(col[rt]){ col[lrt]+=col[rt]; col[rrt]+=col[rt]; sum[lrt]+=col[rt]; sum[rrt]+=col[rt]; col[rt]=0; }}void update(int l,int r,int rt,int L,int R,LL d){ if(L<=l&&r<=R) { col[rt]+=d; sum[rt]+=d; return ; } middle; if(col[rt]!=0) pushdown(rt,r-l+1); if(L<=m) update(lson,L,R,d); if(R>m) update(rson,L,R,d); pushup(rt);}LL query(int l,int r,int rt,int L,int R){ if(L<=l&&r<=R) return sum[rt]; if(col[rt]) pushdown(rt,r-l+1); middle; LL ret=-1e18; if(L<=m) ret=max(query(lson,L,R),ret); if(R>m) ret=max(ret,query(rson,L,R)); return ret;}void dfs(int u,int fa,LL c){ p1[u]=++ti; val[ti]=c; for(int i=head[u];i!=-1;i=edge[i].next){ int v=edge[i].v; if(v==fa) continue; dfs(v,u,c+a[v]); } p2[u]=ti;}int main(){ int t,kase=0; cin>>t; while(t--){ int n,m; cin>>n>>m; init(); for(int i=1;i<n;i++){ int x,y; scanf("%d%d",&x,&y); add_edge(x,y); add_edge(y,x); } for(int i=0;i<n;i++) scanf("%d",&a[i]); kase++; printf("Case #%d:\n",kase); dfs(0,-1,a[0]); build(1,ti,1); while(m--){ int op,x; LL y; scanf("%d%d",&op,&x); if(op==0){ scanf("%I64d",&y); update(1,ti,1,p1[x],p2[x],y-a[x]); a[x]=y; } else printf("%I64d\n",query(1,ti,1,p1[x],p2[x])); } } return 0;}
1004
额。。。不会
1005
给你一个字符串的定义,就是里面有B也有D,然后有filp操作,就是把B变成D,D变成B,然后还有反向操作,就是把字符串倒置
然后问你在区间
第一反应这题肯定是求
然后就是怎么求1-x之间有多少个B的问题了,我们先打表找出,每个字符串k,它的长度len和里面含有的B的个数f,
然后对于字符串1-x,我们可以找到一条最长的,但是长度小于等于R的,完整的串k,如果长度正好为x,就可以
否则就是考虑k串后面还多几个,后面是还多
代码:
#include <map>#include <set>#include <stack>#include <queue>#include <cmath>#include <string>#include <vector>#include <cstdio>#include <cctype>#include <cstring>#include <sstream>#include <cstdlib>#include <iostream>#include <algorithm>#pragma comment(linker,"/STACK:102400000,102400000")using namespace std;#define MAX 205#define MAXN 6005#define maxnode 15#define sigma_size 30#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1#define lrt rt<<1#define rrt rt<<1|1#define middle int m=(r+l)>>1#define LL long long#define ull unsigned long long#define mem(x,v) memset(x,v,sizeof(x))#define lowbit(x) (x&-x)#define pii pair<int,int>#define bits(a) __builtin_popcount(a)#define mk make_pair#define limit 10000//const int prime = 999983;const int INF = 0x3f3f3f3f;const LL INFF = 0x3f3f;const double pi = acos(-1.0);const double inf = 1e18;const double eps = 1e-8;const LL mod = 1e9+7;const ull mx = 133333331;/*****************************************************/inline void RI(int &x) { char c; while((c=getchar())<'0' || c>'9'); x=c-'0'; while((c=getchar())>='0' && c<='9') x=(x<<3)+(x<<1)+c-'0'; }/*****************************************************/LL f[70];LL len[70];void init(){ len[1]=1; f[1]=1; for(int i=2;;i++){ len[i]=len[i-1]*2+1; f[i]=len[i-1]+1; if(len[i]>=1e18) break; }}LL solve(LL x){ if(x==0) return 0; int k=1; for(;;k++){ if(len[k]>x) break; } k--; if(len[k]==x){ return f[k]; } else return solve(2*len[k]-x+1)+x-len[k];}int main(){ //freopen("in.txt","r",stdin); int t; cin>>t; init(); while(t--){ LL l,r; scanf("%I64d%I64d",&l,&r); printf("%I64d\n",solve(r)-solve(l-1)); } return 0;}
1006
给你n个人的编号,编号就是他的值,然后排队,每次放进去一个人的时候可以加上一个值,这个值是他和他前面的所有人里面的最小值,但是有一些限制,就是有的人必须在有的人后面。求最后得到的和的最大值
首先我们考虑和要最大,那必须是大的人先放,再放小的,但是又有限制,就好比点的入度,就是一个点必须在另外个点的前面,拓扑序,所以我们可以模拟拓扑排序,把没有限制的点放进优先队列里,然后往外面取,每次取一个就接触它对别的点的限制,然后记录一个从第一个点到它的最小值就可以了
代码:
#include <map>#include <set>#include <stack>#include <queue>#include <cmath>#include <string>#include <vector>#include <cstdio>#include <cctype>#include <cstring>#include <sstream>#include <cstdlib>#include <iostream>#include <algorithm>#pragma comment(linker,"/STACK:102400000,102400000")using namespace std;#define MAX 100005#define MAXN 6005#define maxnode 15#define sigma_size 30#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1#define lrt rt<<1#define rrt rt<<1|1#define middle int m=(r+l)>>1#define LL long long#define ull unsigned long long#define mem(x,v) memset(x,v,sizeof(x))#define lowbit(x) (x&-x)#define pii pair<int,int>#define bits(a) __builtin_popcount(a)#define mk make_pair#define limit 10000//const int prime = 999983;const int INF = 0x3f3f3f3f;const LL INFF = 0x3f3f;const double pi = acos(-1.0);//const double inf = 1e18;const double eps = 1e-8;const LL mod = 1e9+7;const ull mx = 133333331;/*****************************************************/inline void RI(int &x) { char c; while((c=getchar())<'0' || c>'9'); x=c-'0'; while((c=getchar())>='0' && c<='9') x=(x<<3)+(x<<1)+c-'0'; }/*****************************************************/vector<int> v[MAX];int deg[MAX];int main(){ int t,kase=0; cin>>t; while(t--){ int n,m; cin>>n>>m; for(int i=1;i<=n;i++) v[i].clear(); mem(deg,0); for(int i=0;i<m;i++){ int a,b; scanf("%d%d",&a,&b); v[a].push_back(b); deg[b]++; } priority_queue<int> q; for(int i=1;i<=n;i++){ if(deg[i]==0) q.push(i); } int mini=INF; LL ans=0; while(!q.empty()){ int x=q.top();q.pop(); mini=min(mini,x); ans+=mini; for(int i=0;i<v[x].size();i++){ deg[v[x][i]]--; if(deg[v[x][i]]==0) q.push(v[x][i]); } } cout<<ans<<endl; } return 0;}
- 2016"百度之星" - 初赛(Astar Round2A)题解
- 2016"百度之星" - 初赛(Astar Round2A)题解
- 2016百度之星 - 初赛(Astar Round2A)题解
- 2016"百度之星" - 初赛(Astar Round2A)解题报告
- [Contest] 2016"百度之星" - 初赛(Astar Round2A)
- 2016"百度之星" - 初赛(Astar Round2A)
- 2016"百度之星" - 初赛(Astar Round2A)
- 2016"百度之星" - 初赛(Astar Round2A)解题报告
- 2016"百度之星" - 初赛(Astar Round2A)
- 2016"百度之星" - 初赛(Astar Round2A) 1002
- 2016"百度之星" - 初赛(Astar Round2A)
- 2016"百度之星" - 初赛(Astar Round2A)1001~1006
- 【分治】[2016"百度之星" - 初赛(Astar Round2A)]BD String
- 2016"百度之星" - 初赛(Astar Round2A) 1001 All X(数论知识)
- 2016"百度之星" - 初赛(Astar Round2A)1001 All X (模)
- 2016"百度之星" - 初赛(Astar Round2A)1006 Gym Class(优先队列+拓扑排序)
- 2016"百度之星" - 初赛(Astar Round2A)1003(hdu5692)dfs序+线段树
- HDU 5690 All X(2016"百度之星" - 初赛(Astar Round2A))
- Java不同类型密钥库之PKCS12和JCEKS
- python str.title( )和str.istitle( )
- 输出双螺旋矩阵
- 高效计算余数
- android resources类型
- 2016"百度之星" - 初赛(Astar Round2A)题解
- 实习入职第三天:真机调试,用eclipse单步跟踪查看代码---代码超大的情况
- ARM Linux S3C2440之ADC驱动实现
- 配置Nginx expires缓存实现性能优化
- Bestcoder 大数求余
- No JDK found. Please validate either STUDIO_JDK, JDK_HOME or JAVA_HOME environment variable points
- lower_bound和upper_bound
- Win7_64下Eclipse配置Hadoop2.6.3
- 【玩转常州app】上线啦