mcfx's blog - 数论
/category/math/
-
Codeforces 809E. Surprise me!
/archives/236/
2017-05-25T20:24:07+08:00
###Description
给一棵树,每个点点权 $$a_i$$,保证 $$a_i$$各不相同,现在随机选两个点 $$u,v$$,求 $$f(u,v)=\phi(a_u\cdot a_v)\cdot dis(u,v)$$ 的期望,$$mod\ 10^9+7$$。
链接:[http://codeforces.com/contest/809/problem/E](http://codeforces.com/contest/809/problem/E "http://codeforces.com/contest/809/problem/E")
###Solution
首先,有一个结论:$$\phi(a\cdot b)=\frac{\phi(a)\cdot\phi(b)\cdot g}{\phi(g)},g=gcd(a,b)$$
证明:考虑找一个 $$x$$,使得 $$x|b,gcd(\frac{b}{x},a)=1,gcd(x,\frac{b}{x})=1$$ 且 $$a$$ 包含 $$x$$ 中所有质因子。
那么 $$\phi(a\cdot b)=\phi(a)\cdot x\cdot\phi(\frac{b}{x})=\frac{\phi(a)\cdot\phi(b)\cdot x}{\phi(x)}$$
显然,$$x$$ 是 $$g$$ 的倍数,所以 $$\frac{x}{g}=\frac{\phi(x)}{\phi(g)}$$,所以$$\phi(a\cdot b)=\frac{\phi(a)\cdot\phi(b)\cdot g}{\phi(g)}$$
有了这个结论之后可以考虑点分,那么设 $$dis(x)$$ 表示 $$x$$ 到当前根的距离。
设 $$h(x)=\frac{x}{\phi(x)}$$,那么$$f(u,v)=\phi(a_u)\cdot\phi(a_v)\cdot h(g)\cdot(dis(u)+dis(v)),g=gcd(a_u,a_v)$$
考虑当 $$u$$ 确定时,需要知道 $$\sum\phi(a_v)\cdot h(gcd(a_u,a_v))$$ 和 $$\sum\phi(a_v)\cdot h(gcd(a_u,a_v))\cdot dis(v)$$。
设 $$g(x)=h(x)-\sum[y|x,y\neq x]g(y)$$,那么 $$h(gcd(a_u,a_v))=\sum[x|a_u,x|a_v]g(x)$$
这样就可以直接枚举约数算贡献了。
###Code
```c++
#include
typedef long long ll;
inline void repr(int&a,int b){if(ato,x);
sz[x]+=sz[i->to];
}
}
inline void dfs2(int x,int fa)
{
int t=rsz-sz[x];
for(edge*i=p[x];i;i=i->ne)
if(i->to!=fa&&!vis[i->to])
{
repr(t,sz[i->to]);
dfs2(i->to,x);
}
if(tne)
if(i->to!=fa&&!vis[i->to])
dfs3(i->to,x,dis+1);
}
inline void dfs4(int x,int fa,int dis)
{
int a=phi[w[x]],b=(ll)a*dis%P,A,B;
foe(i,v[w[x]])
{
get(*i,A,B);
ans=(ans+(ll)a*B+(ll)b*A)%P;
}
for(edge*i=p[x];i;i=i->ne)
if(i->to!=fa&&!vis[i->to])
dfs4(i->to,x,dis+1);
}
inline void work(int x)
{
dfs1(x,0);
rsz=nsz=sz[x],nro=x;
dfs2(x,0);
vis[x=nro]=1;
foe(i,v[w[x]])set(*i,phi[w[x]],0);
for(edge*i=p[x];i;i=i->ne)
if(!vis[i->to])
{
dfs4(i->to,x,1);
dfs3(i->to,x,1);
}
fo0(i,qe)g[q[i]]=h[q[i]]=-1;
qe=0;
for(edge*i=p[x];i;i=i->ne)
if(!vis[i->to])work(i->to);
}
int main()
{
fo1(i,N-1)for(int j=i;j
-
BZOJ 2694 & 4659 Lcm
/archives/181/
2017-02-28T00:16:00+08:00
###Description
![fa(1).jpg][1]
###Solution
$$\sum_i^n\sum_j^m[\mu(gcd(i,j))\neq 0]lcm(i,j)$$
$$=\sum_k^n|\mu(k)|\sum_i^{\frac{n}{k}}\sum_j^{\frac{n}{k}}[gcd(i,j)=1]i\cdot j\cdot k$$
$$=\sum_k^n|\mu(k)|\cdot k\sum_d^{\frac{n}{k}}\mu(d)\cdot d^2\sum_i^{\frac{n}{k\cdot d}}\sum_j^{\frac{m}{k\cdot d}}i\cdot j$$
$$=\sum_k^n\sum_d[d|k]\mu(d)\cdot d^2\cdot|\mu(\frac{k}{d})|\cdot\frac{p}{d}\cdot\frac{\frac{n}{k}\cdot(\frac{n}{k}+1)}{2}\cdot\frac{\frac{m}{k}\cdot(\frac{m}{k}+1)}{2}$$
最后的式子,前面是积性函数,后面根号分块
###Code
```c++
#define _GLIBCXX_IOSTREAM
#include
#define N 4000001
int pri[N],pm,f[N],ps[N],pc[N];
bool np[N];
int main()
{
for(int i=2;i
-
BZOJ 3552: 最右非零的数
/archives/154/
2016-12-16T23:38:00+08:00
###Description
给出正整数N(可能有前导0),请求出N!最右非零的数位的值。
###Input
第一行一个数T表示数据组数
下接T行每行一个数N表示一组数据
###Output
对于每组数据,输出一行一个数表示这组数据的答案
###Sample Input
2
5
4
###Sample Output
2
4
###Solution
随便lucas一下就好了,然而懒得写高精,就用了python,于是实力rank last
###Code
```python
T=int(raw_input())
for I in range(T):
n=int(raw_input());t=n;a=0;b=0;c=1
while t>0:t/=2;a+=t
while n>0:c=c*[1,1,2,1,4,4,4,3,4,1][n%10]%5;n/=5;b+=n
a=a-b+1
if a>1:a=0
t=3
while b>0:
if b&1:c=c*t%5
t=t*t%5
b/=2
print (a*5+c*6)%10
```
-
BZOJ 3113: Toy
/archives/87/
2016-11-29T23:24:00+08:00
###Description
外面有一圈N个结点,中心有一个结点与N个结点都相连,总共就是2*N条边,删除N条边,使N+1个点连通,旋转相同视为等价,问有多少种情况。
![1.jpg][1]
###Input
输入N,M
3
-
BZOJ 3884: 上帝与集合的正确用法
/archives/54/
2016-10-16T00:59:00+08:00
###Description
根据一些书上的记载,上帝的一次失败的创世经历是这样的:
第一天, 上帝创造了一个世界的基本元素,称做“元”。
第二天, 上帝创造了一个新的元素,称作“α”。“α”被定义为“元”构成的集合。容易发现,一共有两种不同的“α”。
第三天, 上帝又创造了一个新的元素,称作“β”。“β”被定义为“α”构成的集合。容易发现,一共有四种不同的“β”。
第四天, 上帝创造了新的元素“γ”,“γ”被定义为“β”的集合。显然,一共会有16种不同的“γ”。
如果按照这样下去,上帝创造的第四种元素将会有65536种,第五种元素将会有2^65536种。这将会是一个天文数字。
然而,上帝并没有预料到元素种类数的增长是如此的迅速。他想要让世界的元素丰富起来,因此,日复一日,年复一年,他重复地创造着新的元素……
然而不久,当上帝创造出最后一种元素“θ”时,他发现这世界的元素实在是太多了,以致于世界的容量不足,无法承受。因此在这一天,上帝毁灭了世界。
至今,上帝仍记得那次失败的创世经历,现在他想问问你,他最后一次创造的元素“θ”一共有多少种?
上帝觉得这个数字可能过于巨大而无法表示出来,因此你只需要回答这个数对p取模后的值即可。
你可以认为上帝从“α”到“θ”一共创造了10^9次元素,或10^18次,或者干脆∞次。
一句话题意:
![1.png][1]
###Input
接下来T行,每行一个正整数p,代表你需要取模的值
###Output
T行,每行一个正整数,为答案对p取模后的值
###Sample Input
3
2
3
6
###Sample Output
0
1
4
###HINT
对于100%的数据,T
-
BZOJ1041: [HAOI2008]圆上的整点
/archives/33/
2016-09-18T23:41:00+08:00
###Description
求一个给定的圆(x^2+y^2=r^2),在圆周上有多少个点的坐标是整数。
###Input
只有一个正整数n,n0;i--)
{
int a=nn-i*i,b=sqrt(nn-i*i);
if(b*b==a)
{
int c=2*b*i,d=std::abs(b*b-i*i);
if(!(c&&d))continue;
if(!(f[c*(n/nn)]||f[d*(n/nn)]))
{
f[c*(n/nn)]=f[d*(n/nn)]=1;
ans+=8;
}
}
}
return ans;
}
void dfs(int id,int nn)
{
if(id==cc)
{
ans+=solve(n/nn);
return;
}
dfs(id+1,nn);
dfs(id+1,nn*x[id]);
}
int main()
{
for(int i=2;i
-
BZOJ 1407: [Noi2002]Savage
/archives/27/
2016-09-14T19:14:00+08:00
###Description
![1407.jpg][1]
###Input
第1行为一个整数N(1