2017.10.2 QBXT 模拟赛
T1
我们所要求得是(a*b)|x
也就是 使(a*b)的倍数小于x的个数之和 1<=x<=n
我们可以 找一个c使得 (a*b*c)<=x
由于我们所求的是一个三元有序对 即 (1,2,3) 与 (1,3,2) 是两种不同的方案数
所以 我们可以强制规定 a<b<c
最坏的情况是(a*a*a)==x 所以我们就可以确定a的枚举范围 就是n开三次根号
同理 b最大枚举到 sqrt(n/a)
n/(a*b) 即为 c 由于c>b>a 所以 我们枚举的c是大于b的
c的实际个数为 n(a*b)-b
每一个三元有序对一共有六种变换方式 最后*6加进ans
还有一种情况是 a,b,c 中有两个数相等 例如 a==b>c
我们只需要枚举 c==n/(a*a) 的个数
每一个三元有序对 可以有三种变换 枚举的c的个数最后*3 加进ans
最后一种情况就是 a==b==c 对ans的贡献为 1 简单判断一下就好了
#include<cstdio>
#include<cstdlib>
#include<cstring> using namespace std; long long n; #ifdef unix
#define LL "%lld"
#else
#define LL "%I64d"
#endif int main()
{
freopen("a.in","r",stdin);
freopen("a.out","w",stdout); scanf(LL,&n);
long long ans=,tmp=;
for (long long a=,v;a*a<=(v=n/a);a++,ans++)
for (long long b=a+;b*b<=v;b++)
tmp+=n/(a*b)-b;
ans+=tmp*;
tmp=;
for (long long a=,v;(v=a*a)<=n;a++)
{
tmp+=n/v;
if (a*a<=n/a) tmp--;
}
ans+=tmp*;
printf(LL "\n",ans); return ;
}
T2
倍增LCA 巧妙地搞一搞
对于两个人 想要最大的权值 一定要先把对方给封锁
就是 让对方走过的点越少越好
所以 两个人 一定是先对着走
树上任意两个点之间的路径是唯一的 所以两个人碰面的点 也是一定的
即为 两个人之间点数的中位数
这个点用LCA 求出
求出之后 这个点还可能连着多条边
对于先手会先选一颗权值最大的子树 先走一条边
后手会选次大的子树 走一条边
两者退回继续选取要走的子树
直到走不动了
最后ans再加上已经占领的子树的权值 即为最大权值
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm> using namespace std; const int maxn=; int n,m,en,z[maxn*],f[maxn][],q[maxn],depth[maxn],sum[maxn*][],fd[maxn],start[maxn],end[maxn],value[maxn]; struct edge
{
int e,d;
edge *next;
}*v[maxn],ed[maxn<<]; void add_edge(int s,int e,int d)
{
en++;
ed[en].next=v[s];v[s]=ed+en;v[s]->e=e;v[s]->d=d;
} int get(int p,int d)
{
if (d==-) return p;
int x=;
while (d)
{
if (d&) p=f[p][x];
d>>=;
x++;
}
return p;
} int get_lca(int p1,int p2)
{
if (depth[p1]<depth[p2]) swap(p1,p2);
p1=get(p1,depth[p1]-depth[p2]);
int x=;
while (p1!=p2)
{
if (!x || f[p1][x]!=f[p2][x])
{
p1=f[p1][x];
p2=f[p2][x];
x++;
}
else x--;
}
return p1;
} int calc(int p1,int p2)
{
if (p1==f[p2][]) return value[]-value[p2];
else return value[p1]+fd[p1];
} int calcp(int p,int v)
{
int l=start[p]-,r=end[p];
while (l+!=r)
{
int m=(l+r)>>;
if (v>z[m]) l=m;
else r=m;
}
return r;
} int main()
{
freopen("b.in","r",stdin);
freopen("b.out","w",stdout); scanf("%d%d",&n,&m);
int tot=;
for (int a=;a<n;a++)
{
int s,e,d;
scanf("%d%d%d",&s,&e,&d);
tot+=d;
add_edge(s,e,d);
add_edge(e,s,d);
}
depth[]=;
int front=,tail=;
q[]=;
for (;front<=tail;)
{
int now=q[front++];
for (edge *e=v[now];e;e=e->next)
if (!depth[e->e])
{
depth[e->e]=depth[now]+;
fd[e->e]=e->d;
f[e->e][]=now;
int p=now,x=;
while (f[p][x])
{
f[e->e][x+]=f[p][x];
p=f[p][x];
x++;
}
q[++tail]=e->e;
}
}
int cnt=;
for (int a=n;a>=;a--)
{
int now=q[a];
start[now]=cnt+;
for (edge *e=v[now];e;e=e->next)
if (depth[e->e]==depth[now]+)
{
z[++cnt]=value[e->e]+e->d;
value[now]+=value[e->e]+e->d;
}
z[++cnt]=tot-value[now];
end[now]=cnt;
sort(z+start[now],z+end[now]+);
sum[end[now]][]=z[end[now]];
sum[end[now]][]=;
for (int a=end[now]-;a>=start[now];a--)
{
sum[a][]=sum[a+][];
sum[a][]=sum[a+][];
if ((a&)==(end[now]&)) sum[a][]+=z[a];
else sum[a][]+=z[a];
}
cnt++;
}
for (int a=;a<=m;a++)
{
int p1,p2;
scanf("%d%d",&p1,&p2);
int lca=get_lca(p1,p2);
int dist=depth[p1]+depth[p2]-*depth[lca];
int delta=dist/+(dist&);
int px,px1,px2;
if (depth[p1]-depth[lca]<delta) px=get(p2,dist-delta);
else px=get(p1,delta);
if (depth[p1]-depth[lca]<delta-) px1=get(p2,dist-delta+);
else px1=get(p1,delta-);
if (depth[p2]-depth[lca]<dist-delta-) px2=get(p1,delta+);
else px2=get(p2,dist-delta-);
int ans=;
if (p1==px)
{
if (p2==px) ans=sum[start[px]][];
else
{
int v2=calc(px2,px);
int p=calcp(px,v2);
ans=sum[p+][]+sum[start[px]][]-sum[p][];
}
}
else
{
if (p2==px)
{
int v1=calc(px1,px);
int p=calcp(px,v1);
ans=v1+sum[p+][]+sum[start[px]][]-sum[p][];
}
else
{
int v1=calc(px1,px);
int pp1=calcp(px,v1);
int v2=calc(px2,px);
int pp2=calcp(px,v2);
if (pp2==pp1) pp2++;
if (pp1>pp2) swap(pp1,pp2);
ans=v1+sum[pp2+][dist&]+sum[pp1+][-(dist&)]-sum[pp2][-(dist&)]+sum[start[px]][dist&]-sum[pp1][dist&];
}
}
printf("%d\n",ans);
} return ;
}
T3
怀疑人生的搜索加9维DP
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm> using namespace std; #define now pre[a][b][c][d][e][s1][s2][s3][s4]
#define dis(a,b,c,d) (abs(a-c)+abs(b-d)) const int INF=0x3f3f3f3f; int A,B,C,D,E,num[][],value[][][],delta[][][],dp[][][][][][][][][]; char s[]; bool map[][][][]; int main()
{
freopen("c.in","r",stdin);
freopen("c.out","w",stdout); scanf("%d%d%d%d%d",&A,&B,&C,&D,&E);
for (int a=;a<;a++)
{
scanf("%s",s);
int p=;
for (int b=;b<;b++)
{
int px=p;
while (s[px]!=']')
px++;
p++;
num[a][b]=s[p]-'';
p++;
p++;
for (int c=;c<=num[a][b];c++)
{
int v=;
while (s[p]>='' && s[p]<='')
{
v=v*+s[p]-'';
p++;
}
value[a][b][c]=v;
p++;
}
p=px+;
}
}
int base=;
for (int a=;a<;a++)
for (int b=;b<;b++)
if (a>= && a<= && b>= && b<=) ;
else
{
sort(value[a][b]+,value[a][b]+num[a][b]+);
for (int c=;c<=num[a][b];c++)
if (value[a][b][c]-value[a][b][c-]==) base+=A;
for (int c=;c<=;c++)
for (int d=;d<=;d++)
{
if (dis(a,b,c,d)==)
{
for (int e=;e<=num[a][b];e++)
{
delta[c][d][value[a][b][e]]+=B;
delta[c][d][value[a][b][e]-]+=C;
delta[c][d][value[a][b][e]+]+=C;
}
}
if (dis(a,b,c,d)==)
{
for (int e=;e<=num[a][b];e++)
{
delta[c][d][value[a][b][e]]+=D;
delta[c][d][value[a][b][e]-]+=E;
delta[c][d][value[a][b][e]+]+=E;
}
}
}
for (int c=;c<;c++)
for (int d=;d<;d++)
if (dis(a,b,c,d)<= && (c!=a || d!=b) && !map[a][b][c][d])
{
map[a][b][c][d]=map[c][d][a][b]=true;
if (c>= && c<= && d>= && d<=) ;
else
{
int dist=dis(a,b,c,d);
for (int e=;e<=num[a][b];e++)
for (int f=;f<=num[c][d];f++)
{
if (abs(value[a][b][e]-value[c][d][f])==)
{
if (dist==) base+=B;
else base+=D;
}
if (abs(value[a][b][e]-value[c][d][f])==)
{
if (dist==) base+=C;
else base+=E;
}
}
}
}
}
memset(dp,0x3f,sizeof(dp));
dp[][][][][][][][][]=base;
for (int a=;a<;a++)
for (int b=;b<=num[][];b++)
for (int c=;c<=num[][];c++)
for (int d=;d<=num[][];d++)
for (int e=;e<=num[][];e++)
for (int s1=;s1<=;s1++)
for (int s2=;s2<=;s2++)
for (int s3=;s3<=;s3++)
for (int s4=;s4<=;s4++)
if (dp[a][b][c][d][e][s1][s2][s3][s4]!=INF)
{
int v=dp[a][b][c][d][e][s1][s2][s3][s4];
for (int sx1=;sx1<=(b!=num[][]);sx1++)
for (int sx2=;sx2<=(c!=num[][]);sx2++)
for (int sx3=;sx3<=(d!=num[][]);sx3++)
for (int sx4=;sx4<=(e!=num[][]);sx4++)
{
int wmt=;
if (sx1)
{
wmt+=delta[][][a+];
if (s1) wmt+=A;
if (s2) wmt+=C;
if (s3) wmt+=C;
if (s4) wmt+=E;
}
if (sx2)
{
wmt+=delta[][][a+];
if (s1) wmt+=C;
if (s2) wmt+=A;
if (s3) wmt+=E;
if (s4) wmt+=C;
}
if (sx3)
{
wmt+=delta[][][a+];
if (s1) wmt+=C;
if (s2) wmt+=E;
if (s3) wmt+=A;
if (s4) wmt+=C;
}
if (sx4)
{
wmt+=delta[][][a+];
if (s1) wmt+=E;
if (s2) wmt+=C;
if (s3) wmt+=C;
if (s4) wmt+=A;
}
if (sx1 && sx2) wmt+=B;
if (sx1 && sx3) wmt+=B;
if (sx1 && sx4) wmt+=D;
if (sx2 && sx3) wmt+=D;
if (sx2 && sx4) wmt+=B;
if (sx3 && sx4) wmt+=B;
int &t=dp[a+][b+sx1][c+sx2][d+sx3][e+sx4][sx1][sx2][sx3][sx4];
if (t>v+wmt) t=v+wmt;
}
}
int ans=INF;
for (int a=;a<=;a++)
for (int b=;b<=;b++)
for (int c=;c<=;c++)
for (int d=;d<=;d++)
ans=min(ans,dp[][num[][]][num[][]][num[][]][num[][]][a][b][c][d]);
printf("%d\n",ans); return ;
}
2017.10.2 QBXT 模拟赛的更多相关文章
- 2017.10.7 QBXT 模拟赛
题目链接 T1 容斥原理,根据奇偶性进行加减 #include<iostream> #include<cstdio> using namespace std; typedef ...
- 2017.10.3 QBXT 模拟赛
题目链接 T1 模拟 #include <cstring> #include <cstdio> #define N 105000 int L,R; char s[N]; int ...
- 2017.10.6 QBXT 模拟赛
题目链接 T1 Sort 一下与原数组比较 ,若有两个数或者没有数发生位置交换 ,则输出YES ,否则输出NO #include <algorithm> #include <ccty ...
- 2017.10.5 QBXT 模拟赛
题目链接 T1 从小到大排序,用sum记录前缀和,然后枚举1~n个数 ,如果当前的前缀和 + 1小于a[i]的话 那么 sum + 1永远不可能拼出来 直接输出sum + 1 ,否则统计前缀和.最后如 ...
- 2017.10.4 QBXT 模拟赛
题目链接 T1 维护一个单调栈 #include <iostream> #include <cstdio> #define N 500000 #define rep(a,b,c ...
- 2017.10.1 QBXT 模拟赛
题目链接 T1 枚举右端点,前缀和优化.对于当前点x,答案为 sum[x][r]-sum[x][l-1]-(sum[z][r]-sum[z][l-1]) 整理为 sum[x][r]-sum[z][r] ...
- 2017 10.25 NOIP模拟赛
期望得分:100+40+100=240 实际得分:50+40+20=110 T1 start取了min没有用,w(゚Д゚)w O(≧口≦)O T3 代码3个bug :数组开小了,一个细节没注意, ...
- 2017.10.28 QB模拟赛 —— 下午
题目链接 T1 按x值排序 遇到第二种牌插入 遇到第一种牌 查询<=y 的最小值 删除他 splay multiset cys大佬说 multiset就是不去重的set, #include &l ...
- 2017.10.28 QB模拟赛 —— 上午
题目链接 T1 1e18 内的立方数有 1e6个 直接枚举可过 二分最优 考场用set 死慢.. #include <cstdio> int t; long long p; int ma ...
随机推荐
- PCL推荐的命名规范(1)
博客转载自:http://www.pclcn.org/study/shownews.php?lang=cn&id=209 文件命名 所有的文件名单词之间应该用下划线隔开,例 如unordere ...
- TripAdvisor architecture 2011/06
http://highscalability.com/blog/2011/6/27/tripadvisor-architecture-40m-visitors-200m-dynamic-page-vi ...
- 转:JDBC Request使用方法
1. 下载mysql jar包 下载mysql jar包 http://dev.mysql.com/downloads/connector/j/ 网盘下载地址:mysql-connector-ja ...
- g2o中setparameterid(0,0)方法
其中两个参数的含义: 第二个参数是优化器内添加的参数的id.当你调用addEdge来添加这条边时,会根据第二个参数的id,把相应的参数地址给边,以后边内的成员函数,就根据第一个参数,拿到这个地址.
- vmware中centos6.5无法启动拷贝出里面的资料的方法
先说一下我的环境:windows7-x64位机器下安装的vmware虚拟机,里面安装的是centos6.5-x64位的系统. 系统崩溃的原因:从cenos拖拽一个文件到win7下,结果就卡死了.整个系 ...
- UVaLive 4094 WonderTeam (贪心)
题意:有n支队伍,每两支队伍打两场比赛(主客场各一次),胜得3分,平得1分,输不得分,比赛结束之后会评选出一个梦之队, 梦之队满足以下条件:进球总数最多,胜利场数最多,丢求总数最少,三个都不能并列,求 ...
- tar,jar和war都是什么
jar 即Java Archive,java的类进行编译生成的class文件,通常是开发时要引用通用类,打成包便于存放管理. 但如果直接发布这些class文件的话会很不方便,所以就把许多的class文 ...
- GoWeb开发_Iris框架讲解(一)
Golang介绍 Go语言是谷歌推出的一种全新的编程语言,可以在不损失应用程序性能的情况下降低代码的复杂性.谷歌首席软件工程师罗布派克(Rob Pike)说:我们之所以开发Go,是因为过去10多年间软 ...
- 关于spring mvc的配置文件
1. Web.xml <!--配置页面控制器--> <servlet> <servlet-name>spring</servlet-name> < ...
- CSS——弹性盒模型
弹性盒子是 CSS3 的一种新的布局模式. CSS3 弹性盒( Flexible Box 或 flexbox),是一种当页面需要适应不同的屏幕大小以及设备类型时确保元素拥有恰当的行为的布局方式. 这东 ...