10.5考试总结
来源:互联网 发布:网络用语2016最新 编辑:程序博客网 时间:2024/06/01 22:21
B组:
命运
50分:最小生成树,每两个点连个边
60分(考试分数):当只有1维时,只需对所有点坐标从小到大排序,选相邻的两个点连边即可
100分:发现若答案存在某条边
#include<algorithm>#include<ctype.h>#include<cstdio>#define N 100020using namespace std;inline int read(){ int x=0,f=1;char c; do {c=getchar();if(c=='-') f=-1;} while(!isdigit(c)); do x=(x<<3)+(x<<1)+c-'0',c=getchar(); while(isdigit(c)); return x*f;}int n,k,top;long long ans;int f[N];struct Point{ int pos[7],bh;}a[N];struct Edge{ int x,y,k; Edge(int _=0,int __=0,int ___=0):x(_),y(__),k(___){}}q[1000050];inline void add(int x,int y,int k){ q[++top]=Edge(x,y,k);}inline int abs(int a){return a>0?a:-a;}int find(int k){return f[k]==k?f[k]:f[k]=find(f[k]);}inline void link(int x,int y){ int fx=find(x),fy=find(y); f[fx]=fy;}inline bool cmp(Edge a,Edge b){return a.k<b.k;}inline bool cmp1(Point a,Point b){return a.pos[1]<b.pos[1];}inline bool cmp2(Point a,Point b){return a.pos[2]<b.pos[2];}inline bool cmp3(Point a,Point b){return a.pos[3]<b.pos[3];}inline bool cmp4(Point a,Point b){return a.pos[4]<b.pos[4];}inline bool cmp5(Point a,Point b){return a.pos[5]<b.pos[5];}inline void solve(){ for(int i=1;i<=k;i++){ if(i==1)sort(a+1,a+n+1,cmp1); if(i==2)sort(a+1,a+n+1,cmp2); if(i==3)sort(a+1,a+n+1,cmp3); if(i==4)sort(a+1,a+n+1,cmp4); if(i==5)sort(a+1,a+n+1,cmp5);//按照5维排序 for(int j=2;j<=n;j++){//连边,注意编号可能被打乱,要记录一下 add(a[j-1].bh,a[j].bh,abs(a[j].pos[i]-a[j-1].pos[i])); } } sort(q+1,q+top+1,cmp); for(int i=1;i<=n;i++) f[i]=i;//最小生成树 for(int i=1,cnt=0;i<=top&&cnt<=n-1;i++){ int fx=find(q[i].x),fy=find(q[i].y); if(fx==fy) continue; link(fx,fy); ans+=q[i].k; cnt++; } printf("%lld",ans);}int main(){ n=read();k=read(); for(int i=1;i<=n;i++) for(int j=1;j<=k;j++) a[i].pos[j]=read(),a[i].bh=i; solve();return 0;}
幻想
spfa,
#include<algorithm>#include<ctype.h>#include<cstdio>#include<queue>#define N 10020#define M 2000200#define int long long#define INF 214748364700000000llusing namespace std;inline int read(){ int x=0,f=1;char c; do {c=getchar();if(c=='-') f=-1;} while(!isdigit(c)); do x=(x<<3)+(x<<1)+c-'0',c=getchar(); while(isdigit(c)); return x*f;}queue<int>q;int n,m,k,x,y,z,s,t,top;int Dis[N],fir[N];struct Edge{ int nex,to,k; Edge(int _=0,int __=0,int ___=0):to(_),nex(__),k(___){}}nex[M];inline void add(int x,int y,int k){ nex[++top]=Edge(y,fir[x],k); fir[x]=top;}bool b[N];inline bool spfa1(){ while(!q.empty()) q.pop(); for(int i=1;i<=n;i++) Dis[i]=INF,b[i]=false; Dis[s]=0;q.push(s);b[s]=true; while(!q.empty()){ int x=q.front();q.pop();b[x]=false; for(int i=fir[x];i;i=nex[i].nex) if(Dis[nex[i].to]>Dis[x]+nex[i].k){ Dis[nex[i].to]=Dis[x]+nex[i].k; if(!b[nex[i].to]){ b[nex[i].to]=true; q.push(nex[i].to); } } } return Dis[t]==INF;}int dis[N][55],ans;bool d[N][55];inline void spfa(){ while(!q.empty()) q.pop(); for(int i=1;i<=n;i++){ for(int j=0;j<=k;j++) dis[i][j]=INF; dis[i][0]=Dis[i]; b[i]=false; } for(int j=1;j<=k;j++){//从小到大枚举j dis[s][j]=0;q.push(s);b[s]=true; while(!q.empty()){ int x=q.front();q.pop();b[x]=false; for(int i=fir[x];i;i=nex[i].nex){ if(dis[nex[i].to][j]>dis[x][j]+nex[i].k){ dis[nex[i].to][j]=dis[x][j]+nex[i].k; if(!b[nex[i].to]){ b[nex[i].to]=true; q.push(nex[i].to); } } if(dis[nex[i].to][j]>dis[x][j-1]+nex[i].k/2){ dis[nex[i].to][j]=dis[x][j-1]+nex[i].k/2; if(!b[nex[i].to]){ b[nex[i].to]=true; q.push(nex[i].to); } } } } }}inline void solve(){ spfa(); ans=INF; for(int i=0;i<=k;i++) ans=min(ans,dis[t][i]); printf("%lld",ans);}main(){ n=read();m=read();k=read(); s=read();t=read(); for(int i=1;i<=m;i++){ x=read();y=read();z=read(); add(x,y,z);add(y,x,z); } if(spfa1()){ printf("baka"); return 0; }//判断是否联通 if(k==0){ printf("%lld",Dis[t]); return 0; }//水分.. solve();return 0;}
读书
Meet-in-Middle…
考虑m为0的情况,则只要让体力消耗小于k即可
在MiM后对左右两段消耗体力值从小到大排序,定义两个指针i,j分别指向s1的开头和s2的结尾
固定i,从右到左枚举j直到合法,此时的j即为可统计的答案,下次查找只需将i右移一位,接着左移j即可
如果m不为0,怎么办?
采用类似的思想,不同的是按照能造成的伤害排序,伤害是否合法按照刚才那样处理就可以,对于统计体力在给定范围内的,开个权值树状数组统计一下就好(见代码)
#include<algorithm>#include<ctype.h>#include<cstdio>#define N 27using namespace std;inline int read(){ int x=0,f=1; char c; do {c=getchar();if(c=='-') f=-1;} while(!isdigit(c)); do x=(x<<3)+(x<<1)+c-'0',c=getchar(); while(isdigit(c)); return x*f;}int n,m,k;long long ans=0;int top1,top2;int q[1000020];inline void add(int x,int k){ for(;x<=1000000;x=x+(x&-x)) q[x]+=k;}inline int Sum(int x){ int sum=0; for(;x;x=x-(x&-x)) sum=sum+q[x]; return sum;}struct Round{ int p,def,atk,a,b,c;}a[N];struct Data{ int res,hp; Data(int _=0,int __=0):res(_),hp(__){}}s1[600500],s2[600500];//res:消耗多少体力 hp:造成多少伤害void dfs(int x,int res,int hp){ if(x==(n>>1)+1){ s1[++top1]=Data(res,hp); return; } dfs(x+1,res+a[x].p,hp+a[x].a); dfs(x+1,res+a[x].p-a[x].def,hp+a[x].a-a[x].b); dfs(x+1,res+a[x].p+a[x].atk,hp+a[x].a+a[x].c); return;}//Meet-in-Middle leftvoid dfs1(int x,int res,int hp){ if(x==n+1){ s2[++top2]=Data(res,hp); return; } dfs1(x+1,res+a[x].p,hp+a[x].a); dfs1(x+1,res+a[x].p-a[x].def,hp+a[x].a-a[x].b); dfs1(x+1,res+a[x].p+a[x].atk,hp+a[x].a+a[x].c); return;}//Meet-in-Middle rightinline bool cmp(Data a,Data b){ return a.hp>b.hp;}inline void solve(){ dfs(1,0,0); dfs1(n/2+1,0,0); sort(s1+1,s1+top1+1,cmp); sort(s2+1,s2+top2+1,cmp);//这次按造成伤害值从小到大排序 int j=top2; for(int i=1;i<=j;i++) add(s2[i].res,1); for(int i=1;i<=top1;i++) { while(s2[j].hp+s1[i].hp<m && j) {add(s2[j].res,-1);j--;}//让造成伤害值始终大于m if(k-s1[i].res<0) continue; ans=ans+Sum(k-s1[i].res);//统计此时满足体力限定的方案个数 } printf("%lld",ans); return;}inline void init();int main(){ init(); solve(); return 0;}inline void init(){//读入... n=read();m=read();k=read(); for(int i=1;i<=n;i++)a[i].p=read(); for(int i=1;i<=n;i++)a[i].a=read(); for(int i=1;i<=n;i++)a[i].def=read(); for(int i=1;i<=n;i++)a[i].b=read(); for(int i=1;i<=n;i++)a[i].atk=read(); for(int i=1;i<=n;i++)a[i].c=read();}
A组:
Return
题目描述
他曾经将此作为一种高贵的气质、只留下潇洒的背影,直到他品尝了孤独的滋味、听到黑暗的夜里一个人默默的心跳。他向那个背影追去,却发现又回到原点。
现实中他依然在奔跑,他越跑越快,知道回到最初的时间,于是他又重新开始。然而轮回中、他早已死去,只有在梦魇中他才有一丝气息。
奔跑中的每一秒他都有一个速度,在现实中当然是越来越快的,直到回到最初的速度;在梦里,他同样在奔跑,不过梦,终究只是现实的闪回罢了,逃脱不了无尽的命运。现在你知道他在梦里每一秒的速度,梦里的一秒、即为现实中的一秒。请你统计一下梦里有多少秒在现实中满足 (现实中的上一秒的速度+这一秒的速度)mod(231 -1)=现实中的下一秒的速度。
这是一个长长的梦,所以现实中的每一秒都会在梦里出现的,不必担心会有断裂的时空存在。
输入描述
多组数据。
每组数据第一行一个整数 n,表示梦的长度。
第二行有 n 个整数,第 i 个整数表示梦中第 i 秒他的速度,保证在[0,231 ).
输出描述
对于第 i 组数据输出一行 Case #i: answer;如果现实只有一秒,他以恒定的速度在宇宙中茕茕而行,就像生活那样单调,就像清水一样淡,那么输出-1.
输入样例
3
1 2 3
5
1 2 3 5 7
6
2 3 1 2 7 5
输出样例
Case #1: 1
Case #2: 2
Case #3: 3
数据范围
对于%100 的数据,保证数据组数≤10.
对于%10 的数据,有 n=1.
对于%30 的数据,有 n≤3
对于%60 的数据,有 n≤1000
对于%100 的数据,有 n≤10000
样例3的解释:
现实中的速度是…5 7 1 2 3 5 7 1 2 3 5 7 1 2…
所以在梦里第一秒的速度是2,那么它在现实中前一秒是1,后一秒是3,所以1+2=3,是符合条件的。
梦中第二秒是3,2+3=5,get!
梦中第三秒是1,7+1≠2.
第四秒是2,1+2=3.
第五秒是7,5+7≠1.
第六秒是5,3+5≠7
所以答案就是3啦~
语文题…读懂之后才发现特别水…
sort+unique就行了…
对了-1还要特判一下
#include<algorithm>#include<ctype.h>#include<cstdio>#define N 10050#define int long long#define MOD 2147483647using namespace std;inline int read(){ int x=0,f=1;char c; do {c=getchar();if(c=='-') f=-1;} while(!isdigit(c)); do x=(x<<3)+(x<<1)+c-'0',c=getchar(); while(isdigit(c)); return x*f;}int n,top,pre,ans,cnt,p,x;int a[N],b[N];main(){ while(scanf("%lld",&n)!=EOF){ ans=0ll; for(int i=1;i<=n;i++) b[i]=a[i]=read(); sort(b+1,b+n+1); top=unique(b+1,b+n+1)-b-1; if(top==1){ printf("Case #%lld: %d\n",++p,-1); continue; }//特判无解 b[0]=b[top];b[top+1]=b[1]; for(int i=1;i<=n;i++){ x=lower_bound(b+1,b+top+1,a[i])-b; if((b[x-1]+a[i])%MOD==b[x+1]) ans++; } printf("Case #%lld: %lld\n",++p,ans); }return 0;}
One
题目描述
终于都走了。
曾经有 n-1 个人在他身边,然而现在只剩他一个人。
Who are you?Who am I?Why am I here?
走的越来越慢,人越来越少,可终于还是只剩一个了呢。
他们围成一圈,随机了一个人作为 1 号,然后逆时针依次编号。1号开始报数,报到 1,他走了;然后 2 号开始报数,2 号报了 1,3 号报了 2,于是 3 号也走了……每一轮都从上一次出局的下一个人开始报数,第 i 轮从 1 报到 i,报 i 的人出局。
直到只剩他一个人。却早已不记得他自己是谁。
他想知道他最初的号码,那上面承载着最初的记忆和最原始的愿望。
输入描述
第一行一个数 T 表示数据组数。
接下来 T 行,每行一个整数 n。
输出描述
共 T 行,每行一个数表示他原本的编号。
输入样例
2
2
3
输出样例
2
2
数据范围
对于%100 的数据,T≤10
对于%10 的数据,n≤5
对于%30 的数据,n≤3000
对于%60 的数据,n≤10000
对于%100 的数据,n≤10^7
约瑟夫问题
要事先了解一下如何线性推约瑟夫
最后得出的就是F(i)=(F(i-1)+M)%i,F(i)代表报i次数剩下的人是谁,M是每多少个人走一个
不同的是M是变化的,特殊处理一下就可以
关于公式怎么推的,请戳这里
#include<ctype.h>#include<cstdio>using namespace std;inline int read(){ int x=0,f=1;char c; do {c=getchar();if(c=='-') f=-1;} while(!isdigit(c)); do x=(x<<3)+(x<<1)+c-'0',c=getchar(); while(isdigit(c)); return x*f;}int n,x,T;int main(){ T=read(); while(T--){ n=read(); x=0; for(int i=2;i<=n;i++) x=(n-i+1+x)%i; printf("%d\n",x+1); }return 0;}
Phi
数论题,事实上就是个爆搜..
注意大质数的情况
#include<iostream>#include<cstdlib>#include<cstdio>#include<cmath>#define N 100005#define int long longusing namespace std;int n,m,cnt,pri[N];bool b[N];long long ans;bool check(int x){ int sz=(int)sqrt(x); for(int i=1;pri[i]<=sz;i++) if(!(x%pri[i])) return 0; return 1;}void dfs(int k,int now,long long sum){ if(sum>=ans) return; if(now==1){ans=sum;return;} if(now>m && check(now+1)) ans=min(ans,sum*(now+1)); for(int i=k+1;pri[i]-1<=m;i++){ if(pri[i]-1>now) break; if(!(now%(pri[i]-1))){ int x=now/(pri[i]-1); long long y=sum*pri[i]; dfs(i,x,y); while(!(x%pri[i])){ x/=pri[i]; y*=pri[i]; dfs(i,x,y); } } }}main(){ scanf("%d",&n);m=(int)sqrt(n); if(n==1){ printf("1"); return 0; } for(int i=2;i<=50000;i++){ if(!b[i])pri[++cnt]=i; for(int j=1;j<=cnt&&i*pri[j]<=50000;j++){ b[i*pri[j]]=true; if(!(i%pri[j])) break; } } ans=2147483648ll; dfs(1,n,1); if(ans<=2147483647) printf("%lld",ans); else printf("-1");return 0;}
- 10.5考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- CYaRon数据生成器源代码分析(0)——前言
- 《数据结构》实验二:线性表综合实验——(4)静态链表
- Linux系统中的tomcat定时重启脚本
- struts2的理解
- redhat6更改centos yum源
- 10.5考试总结
- c#读取csv文件成DataTable,将DataTable数据存储为csv格式文件
- vim的配置(适合编程)
- JAVA面向对象编程——多态
- js鼠标滚轮事件兼容
- 百度2017春招笔试的部分编程题
- python实战游戏开发——安装pygame
- java面试题(上)
- 函数名做实参传递及程序实例