20200616题解
starseven
2020-06-16 20:52:26
# 等式/equal
- 题目:
给出$n$,求
$$\frac{1}{x}+\frac{1}{y}=\frac{1}{n}$$
中$x$,$y$的解集个数($x\leq y$)
------
- 分析
因为($x\leq y$),所以我们可以很明显的想到设$x=\frac{1}{n+x}$
所以我们可以据此表示$y=\frac{x}{(n)\times(x+n)}$
所以我们现在就是要知道$y$可不可以表示成$\frac{1}{m}$
那么$\frac{1}{y}=m=\frac{(n)\times(x+n)}{x}=\frac{n^2}{x}+n$
所以我们只需要让$\frac{n^2}{x}$为整数
这就很明显的得出:
我们先让$n$分解质因数,然后每一个质因子的数用质因数个数的公式:
$$num_n=\prod\limits_{i\mid n,i\in prime}num[i]$$
然后我们可以看出,每一个小于$n$的可以被$n^2$整除的数,都与一个大于$n$的可以被$n^2$整除的数**一一对应**,所以说最后的答案就显而易见了。
(你想知道为什么一一对应吗,私聊我吧)
- **Codes**
```cpp
#include<cstdio>
#include<iostream>
#include<cstring>
#define ri register int
#define Starseven main
#define ll long long
using namespace std;
ll read();
void write(ll);//要记得自己加换行和空格
ll n,prime[10000+20],num;
ll ans;
bool vis[40000+20];
void Init(){
freopen("equal.in","r",stdin);
freopen("equal.out","w",stdout);
}
void Cut(){
ans=1;
for(ri i=1;i<=num;i++){
ll x=0;
while(n%prime[i]==0) x+=2,n/=prime[i];
ans=(x+1)*ans;
if(n==1) break;
}
if(n!=1) ans=ans*3;
ans+=1;
ans/=2;
write(ans);
puts("");
}
int Starseven(void){
Init();
ll t=read();
for(ri i=2;i<=40000;i++){
if(!vis[i]) prime[++num]=i;
for(ri j=1;j<=num&&prime[j]*i<=40000;j++){
vis[i*prime[j]]=true;
if(!i%prime[j]) break;
}
}
while(t--){
n=read();
Cut();
}
return 0;
}
ll read(){
char ch=getchar();
ll re=0,op=1;
while(ch<'0'||ch>'9'){
if(ch=='-') op=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
re=(re<<3)+(re<<1)+ch-'0';
ch=getchar();
}
return re*op;
}
void write(ll x){
if(x<0){
putchar('-');
x=-x;
}
if(x>9) write(x/10);
putchar(x%10+'0');
return ;
}
```
----------
# 湾海公园/park
- 题目
给你一个$n$个点,$n$条边的图,保证拆一条边可以变成树,然后每个边都有权值,叫你拆一条边,保证以下两点
- 保证是棵树
- 保证此时树的直径最短
然后输出此时的树的直径
--------------
- 分析
我们首先可以知道,此时的图由于拆一个边就可以变成树,所以这个图里只有一个环
那我们先用无向图的拓扑排序来求出环。这期间可以处理出环上每个点
-