题目链接

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 模拟赛的更多相关文章

  1. 2017.10.7 QBXT 模拟赛

    题目链接 T1 容斥原理,根据奇偶性进行加减 #include<iostream> #include<cstdio> using namespace std; typedef ...

  2. 2017.10.3 QBXT 模拟赛

    题目链接 T1 模拟 #include <cstring> #include <cstdio> #define N 105000 int L,R; char s[N]; int ...

  3. 2017.10.6 QBXT 模拟赛

    题目链接 T1 Sort 一下与原数组比较 ,若有两个数或者没有数发生位置交换 ,则输出YES ,否则输出NO #include <algorithm> #include <ccty ...

  4. 2017.10.5 QBXT 模拟赛

    题目链接 T1 从小到大排序,用sum记录前缀和,然后枚举1~n个数 ,如果当前的前缀和 + 1小于a[i]的话 那么 sum + 1永远不可能拼出来 直接输出sum + 1 ,否则统计前缀和.最后如 ...

  5. 2017.10.4 QBXT 模拟赛

    题目链接 T1 维护一个单调栈 #include <iostream> #include <cstdio> #define N 500000 #define rep(a,b,c ...

  6. 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] ...

  7. 2017 10.25 NOIP模拟赛

    期望得分:100+40+100=240 实际得分:50+40+20=110 T1 start取了min没有用,w(゚Д゚)w    O(≧口≦)O T3 代码3个bug :数组开小了,一个细节没注意, ...

  8. 2017.10.28 QB模拟赛 —— 下午

    题目链接 T1 按x值排序 遇到第二种牌插入 遇到第一种牌 查询<=y 的最小值 删除他 splay multiset cys大佬说 multiset就是不去重的set, #include &l ...

  9. 2017.10.28 QB模拟赛 —— 上午

    题目链接 T1 1e18 内的立方数有 1e6个 直接枚举可过 二分最优 考场用set  死慢.. #include <cstdio> int t; long long p; int ma ...

随机推荐

  1. 托管C++——在C#中使用C++

    下面就用一个完整的实例来详细说明怎样用托管C++封装一个C++类以提供给C#使用. 现有一个Detector类需要使用,首先,要创建一个托管C++的DLL工程DAADll,然后在里面添加下面的代码: ...

  2. 如何让IntPtr指向一块内存,以及托管内存与非托管内存的相互转化

    IntPtr idp= IntPtr.Zero; StringBuilder idata = new StringBuilder("000000"); string idata = ...

  3. http verbs--Method Definitions

    http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html part of Hypertext Transfer Protocol -- HTTP/1. ...

  4. win form treeview添加节点

    //实例代码: /// <summary> /// 添加节点事件 /// </summary> /// <param name="tnodes"> ...

  5. UnityShader实例09:Stencil Buffer&Stencil Test

    http://blog.csdn.net/u011047171/article/details/46928463 Stencil Buffer&Stencil Test 在开始前先吐槽下uni ...

  6. unity获取设备分辨率

    设备分辨率 using UnityEngine; using System.Collections; public class ExampleClass : MonoBehaviour { void ...

  7. poj1837 Balance

    Balance  POJ - 1837 题目大意: 有一个天平,天平左右两边各有若干个钩子,总共有C个钩子,有G个钩码,求将钩码全部挂到钩子上使天平平衡的方法的总数. 其中可以把天枰看做一个以x轴0点 ...

  8. Python学习笔记(字典)

    今天学习一个python中的基本类型--字典(dictionary) 字典这种数据结构有点像我们平常用的通讯录,有一个名字和这个名字对应的信息.在字典中,名字叫做“键”,对应的内容信息叫做“值”.字典 ...

  9. 用IDEA写出第一个java web

    今天学习到如何创建新的java web,笔者使用的是IDEA,以下有详细的参考链接,如下: 参考链接:https://blog.csdn.net/zhdkong/article/details/789 ...

  10. kettle的使用(ETL,数据仓库技术)

    本周项目上用到了kettle并且需要做任务调度,听老师说用kettle自带的调度不大稳定于是便baidu了下,参照这篇文章完成了通过kitchen的调度,简单说就是通过windows的计划任务来调用. ...