2015 Multi-University Training Contest 1
来源:互联网 发布:mac删除dock图标 编辑:程序博客网 时间:2024/05/21 07:08
官方题解:http://blog.sina.com.cn/s/blog_15139f1a10102vnx5.html
1001
HDU 5288:http://acm.hdu.edu.cn/showproblem.php?pid=5288
题意:给出一个数组\(a[n]\),定义函数\(f(l,r)\)表示在区间\([l,r]\)内没有\(a_i\)的因子的\(i\)的数量,因子的下标不能为\(i\),求
$$\sum_{i=1}^{n}\sum_{j=i}^{n}f(i,j)\mod(10^9+1)$$
题目可以转换成每个\(a_i\)可以贡献的区间个数为\(K_i\),求出所有\(K_i\)之和
要求\(K_i\)就是找左右离\(a_i\)最近的2个因子,求出左右不包含因子的区间长度\(l,r\)
$$K_i=(l+1)\times (r+1)$$
$$ans=\sum_{i=1}^{n}K_i$$
要求出最近的因子可以预处理10000内所有数的因数,在输入的时候记录每个数出现的位置,因为记录是有序的,所以可以找出离\(a_i\)最近的两个因子
#include<cstdio>#include<algorithm>#include<iostream>#include<cmath>#include<cstring>#include<queue>using namespace std;#define MAX(a,b) ((a>b)?(a):(b))#define MIN(a,b) ((a<b)?(a):(b))#define LL __int64#define N 100005#define M 10005#define INF 1<<30#define MOD 1000000007int n;int a[N];vector<int> fac[M];vector<int> sit[M];void init(){ for(int i=1;i<M;++i){ for(int j=i;j<M;j+=i){ fac[j].push_back(i); } }}int main(){ init();while(scanf("%d",&n)!=EOF){ for(int i=1;i<=10000;i++) sit[i].clear(); for(int i=1;i<=n;++i){ scanf("%d",&a[i]); sit[a[i]].push_back(i); } LL ans=0; LL ll,rr; int flag; for(int i=1;i<=n;++i){ ll=0,rr=n+1; for(int j=0;j<fac[a[i]].size();++j){ flag=1; for(int k=0;k<sit[fac[a[i]][j]].size();++k){ if(sit[fac[a[i]][j]][k]<i){ ll=MAX(ll,sit[fac[a[i]][j]][k]); } if(sit[fac[a[i]][j]][k]==i)continue; if(sit[fac[a[i]][j]][k]>i){ rr=MIN(rr,sit[fac[a[i]][j]][k]); break; } } } ll=i-ll-1; rr=rr-i-1; ans=(ans+(ll+1)*(rr+1))%MOD; } printf("%I64d\n",(ans)%MOD);}return 0;}
1002
HDU 5289:http://acm.hdu.edu.cn/showproblem.php?pid=5289
题意:求区间内的数两两之间差小于K的区间个数
RMQ+二分
先预处理出区间最大值和最小值
对于每个\(a_i\)可以用二分找出最大的r值满足区间[i,r]的最大值-最小值<K
#include<cstdio>#include<algorithm>#include<iostream>#include<cmath>#include<cstring>#include<queue>using namespace std;#define MAX(a,b) ((a>b)?(a):(b))#define MIN(a,b) ((a<b)?(a):(b))#define LL __int64#define INF 1<<30const int MAXN = 100010;int dp1[MAXN][20];int dp2[MAXN][20];int mm[MAXN];//初始化RMQ, b数组下标从1开始void initRMQ(int n,int b[]) { mm[0] = -1; for(int i = 1; i <= n; i++) { mm[i] = ((i&(i-1)) == 0)?mm[i-1]+1:mm[i-1]; dp1[i][0] = b[i]; dp2[i][0] = b[i]; } for(int j = 1; j <= mm[n]; j++) for(int i = 1; i + (1<<j) -1 <= n; i++){ dp1[i][j] = max(dp1[i][j-1],dp1[i+(1<<(j-1))][j-1]); dp2[i][j] = min(dp2[i][j-1],dp2[i+(1<<(j-1))][j-1]); }}//查询最大值int rmq1(int x,int y) { int k = mm[y-x+1]; return max(dp1[x][k],dp1[y-(1<<k)+1][k]);}//查询最小值int rmq2(int x,int y) { int k = mm[y-x+1]; return min(dp2[x][k],dp2[y-(1<<k)+1][k]);}int n,k;int a[MAXN];bool judge(int x,int y){ if(rmq1(x,y)-rmq2(x,y)<k) return true; return false;}int main() { int T; scanf("%d",&T); int l,r,m; LL ans; while(T--){ scanf("%d%d",&n,&k); ans=0; for(int i=1;i<=n;++i)scanf("%d",&a[i]); initRMQ(n,a); for(int i=1;i<=n;++i){ l=i,r=n; int e=i; while(l<=r){ m=(l+r)>>1; if(judge(i,m)){ e=m; l=m+1; }else{ r=m-1; } } ans+=(e-i+1); } printf("%I64d\n",ans); } return 0;}
1012
树的删边游戏
从某一棵树上删除一条边,同时删去所有在删除边后不再与根相连的部分。双方轮流进行,无法再进行删除者判定为失败。
定理:
叶子节点的 SG 值为 0;
中间节点的 SG 值为它的所有子节点的 SG 值加 1 后的异或和。
对于建立圆的包含关系树,可以按半径从小到大排序,对于第一个大于并包含它的圆建边,然后break;
当然这是暴力的方法。交C++会TLE,交G++才会AC
#include<cstdio>#include<algorithm>#include<iostream>#include<cmath>#include<cstring>#include<queue>using namespace std;#define MAX(a,b) ((a>b)?(a):(b))#define MIN(a,b) ((a<b)?(a):(b))#define LL __int64#define N 100005#define INF 1<<30struct R{ int x,y,r;}o[N];bool cmp(R a,R b){ return a.r<b.r;}//判断包含关系,i被j包含int judge(int i,int j){ if((o[i].x-o[j].x)*(o[i].x-o[j].x)+(o[i].y-o[j].y)*(o[i].y-o[j].y)<(o[i].r-o[j].r)*(o[i].r-o[j].r)) return 1; return 0;}struct node{ int to,next;}edge[N];int head[N],k;void init(){ k=1; memset(head,0,sizeof(head));}void add(int u,int v){ edge[k].to=v; edge[k].next=head[u]; head[u]=k++;}int dfs(int u){ int ret=0; for(int i=head[u];i;i=edge[i].next){ ret^=(dfs(edge[i].to)+1); } return ret;}int main(){int T;int n;scanf("%d",&T);int ans,flag;while(T--){ init(); ans=0; scanf("%d",&n); for(int i=1;i<=n;++i){ scanf("%d%d%d",&o[i].x,&o[i].y,&o[i].r); } sort(o+1,o+n+1,cmp); for(int i=1;i<=n-1;++i){ flag=0; for(int j=i+1;j<=n;++j){ if(judge(i,j)){ add(j,i); flag=1; break; } } if(!flag){ add(0,i); } } add(0,n); ans=dfs(0); if(ans)printf("Alice\n"); else printf("Bob\n");}return 0;}
(待续。。。)
- 2015 Multi-University Training Contest 1
- 2015 Multi-University Training Contest 1记录
- 2015 Multi-University Training Contest 1
- 2015 Multi-University Training Contest 1
- 2015 Multi-University Training Contest 1
- 2015 Multi-University Training Contest 1
- 2015 Multi-University Training Contest 1
- 2015 Multi-University Training Contest 1
- 2015 Multi-University Training Contest 1
- hdu 5294 Tricks Device 2015 Multi-University Training Contest 1
- hdu 5289 Assignment 2015 Multi-University Training Contest 1
- 2015 Multi-University Training Contest 1 Hdu 5289 Assignment
- 2015 Multi-University Training Contest 1 Hdu 5292 Pocket Cube
- 2015 Multi-University Training Contest 1 Hdu 5297 Y sequence
- 2015 Multi-University Training Contest 1 Hdu5288 OO’s Sequence
- 2015 Multi-University Training Contest 1 题解 BY FZUw
- HDU 5289 Assignment (2015 Multi-University Training Contest 1)
- hdu 5291 Candy Distribution 2015 Multi-University Training Contest 1
- hdu 2066 一个人的旅行(dijkstra)
- 关于Android导入工程时有红色感叹号的解决方案
- c++ 计蒜客第13题整数转换为罗马数字
- 杭电1090 a+b(2)
- 甘特图生产排程(APS)定制开发
- 2015 Multi-University Training Contest 1
- php基础学习笔记
- 【Linux学习笔记】Linux/UNIX系统标准数据类型
- Linux中TCP和UDP发送和接收缓冲区
- String 和 new String()的区别
- 开发环境初始化
- Android Bundle类
- IntentService 编写本地推送
- Google开源命令行参数解析库gflags