description
设 d ( i ) d(i) d(i)为 i i i的因数个数
给定 n , m n,m n,m,求:
∑ i = 1 n ( − 1 ) ∑ j = 1 m d ( i ⋅ j ) \sum_{i=1}^n(-1)^{\sum_{j=1}^m d(i\cdot j)} i=1∑n(−1)∑j=1md(i⋅j)
n ≤ 1 0 7 , m ≤ 1 0 14 n\leq 10^7,m\leq 10^{14} n≤107,m≤1014
solution
发现我们只用关心有几个 j j j可以让 i ⋅ j i\cdot j i⋅j是完全平方数
设 i = p q 1 2 i=pq_1^2 i=pq12,其中 p p p的质因数最高次幂是 1 1 1,那么任意承上一个 p q 2 2 pq_2^2 pq22之后, d ( i ⋅ j ) d(i\cdot j) d(i⋅j)一定是完全平方数
设 f ( i ) f(i) f(i)表示 i i i最小乘上多少之后可以变成一个完全平方数,则 i i i的个数为 ⌊ ⌊ m f ( i ) ⌋ ⌋ \lfloor\sqrt{\lfloor\frac{m}{f(i)}\rfloor}\rfloor ⌊⌊f(i)m⌋⌋,最后一次统计答案就可以
利用线性晒可以 O ( n ) O(n) O(n)解决
code
#include
using namespace std;
# define Rep(i,a,b) for(int i=a;i<=b;i++)
# define _Rep(i,a,b) for(int i=a;i>=b;i--)
# define RepG(i,u) for(int i=head[u];~i;i=e[i].next)
typedef long long ll;
const int N=1e7+5;
template<typename T> void read(T &x){
x=0;int f=1;
char c=getchar();
for(;!isdigit(c);c=getchar())if(c=='-')f=-1;
for(;isdigit(c);c=getchar())x=(x<<1)+(x<<3)+c-'0';
x*=f;
}
ll n,m;
ll f[N];
ll ans;
int prime[N],tot;
bool isprime[N];
int main()
{
freopen("math.in","r",stdin);
freopen("math.out","w",stdout);
memset(isprime,1,sizeof(isprime));
read(n),read(m);
isprime[0]=isprime[1]=0;
f[1]=1;
Rep(i,2,n){
if(isprime[i])prime[++tot]=i,f[i]=i;
for(int j=1;j<=tot&&1ll*i*prime[j]<=n;j++){
isprime[i*prime[j]]=false;
if(i%prime[j]==0){
if(f[i]%prime[j]==0)f[i*prime[j]]=f[i]/prime[j];
else f[i*prime[j]]=f[i]*prime[j];
break;
}
else f[i*prime[j]]=f[i]*prime[j];
}
}
Rep(i,1,n){
ll val=m/f[i];
val=floor(sqrt(1.*val));
if(val&1)ans--;
else ans++;
}
printf("%lld\n",ans);
return 0;
}
description
有 n n n个点,第 i i i个在 t i t_i ti秒出现在 ( x i , y i ) (x_i,y_i) (xi,yi),初始从 ( 0 , 0 ) (0,0) (0,0)开始,问鼠标移动的速度的最大值最小是多少,使得可以点到 k k k个点
答案可以表示成 a b c \frac{a\sqrt b}{c} cab的形式,其中 b b b不含平方因子, gcd ( a , c ) = 1 \gcd(a,c)=1 gcd(a,c)=1
输出 a , b , c a,b,c a,b,c
n , k ≤ 2000 n,k\leq 2000 n,k≤2000
solution
发现可能的距离一共最多有 n 2 n^2 n2种,所以我们可以把他们都存到一个数组里面,按照距离排序,在这个数组上二分,check的时候dp一下就好了
复杂度 O ( n 2 log n 2 ) O(n^2\log n^2) O(n2logn2)
code
#include
using namespace std;
# define Rep(i,a,b) for(int i=a;i<=b;i++)
# define _Rep(i,a,b) for(int i=a;i>=b;i--)
# define RepG(i,u) for(int i=head[u];~i;i=e[i].next)
typedef long long ll;
const int N=2005;
template<typename T> void read(T &x){
x=0;int f=1;
char c=getchar();
for(;!isdigit(c);c=getchar())if(c=='-')f=-1;
for(;isdigit(c);c=getchar())x=(x<<1)+(x<<3)+c-'0';
x*=f;
}
int n,k;
int tot;
int f[N];
struct misaka{
int x,y,t;
bool operator < (const misaka &cmp)const{
return t<cmp.t;
}
}a[N];
struct mikoto{
int a,c;
bool operator < (const mikoto &cmp)const{
return 1ll*a*cmp.c*cmp.c<1ll*cmp.a*c*c;
}
}q[N*N];
int dist(int i,int j){
return (a[i].x-a[j].x)*(a[i].x-a[j].x)+(a[i].y-a[j].y)*(a[i].y-a[j].y);
}
int gcd(int a,int b){
if(!b)return a;
return gcd(b,a%b);
}
bool check(int x){
memset(f,-0x3f,sizeof(f));
f[0]=0;
int res=0;
Rep(i,1,n)
Rep(j,0,i-1)
if(1ll*dist(i,j)*q[x].c*q[x].c<=1ll*q[x].a*(a[i].t-a[j].t)*(a[i].t-a[j].t)){
f[i]=max(f[i],f[j]+1);
res=max(res,f[i]);
}
return res>=k;
}
int main()
{
freopen("osu.in","r",stdin);
freopen("osu.out","w",stdout);
read(n),read(k);
Rep(i,1,n)read(a[i].t),read(a[i].x),read(a[i].y);
sort(a+1,a+n+1);
Rep(i,1,n)
Rep(j,i+1,n){
tot++;
int fz=dist(i,j);
q[tot].c=a[j].t-a[i].t;
q[tot].a=fz;
}
sort(q+1,q+tot+1);
int l=1,r=tot,ans=0;
while(l<=r){
int mid=l+r>>1;
if(check(mid))ans=mid,r=mid-1;
else l=mid+1;
}
int a=1,b=q[ans].a,c=q[ans].c;
for(int i=2;i*i<=b;i++)
while(b%(i*i)==0)b/=(i*i),a*=i;
int GCD=gcd(a,c);
a/=GCD,c/=GCD;
printf("%d %d %d\n",a,b,c);
return 0;
}
description
给定一个 n n n个点 m m m条边的无向图,如果两点之间存在两条不相交的路径,那么我们说这个点对是安全的
现在给出 q q q次询问,每次询问在 ( x , y ) (x,y) (x,y)之间连上一条边之后,会增加多少个安全点对
n , q ≤ 2 × 1 0 5 , m ≤ 4 × 1 0 5 n,q\leq 2\times 10^5,m\leq 4\times 10^5 n,q≤2×105,m≤4×105
solution
显然缩点,考虑 ( x , y ) (x,y) (x,y)连边之后,任意两个不同的点双的两个点都会变成安全的,所以贡献是
∑ x ( ∑ x − x ) = ( ∑ x ) 2 − ∑ x 2 \sum x(\sum x-x)=(\sum x)^2-\sum x^2 ∑x(∑x−x)=(∑x)2−∑x2
所以在树上倍增预处理一下就好了
code
#include
using namespace std;
# define Rep(i,a,b) for(int i=a;i<=b;i++)
# define _Rep(i,a,b) for(int i=a;i>=b;i--)
# define RepG(i,u) for(int i=head[u];~i;i=e[i].next)
typedef long long ll;
const int N=3e5+5;
template<typename T> void read(T &x){
x=0;int f=1;
char c=getchar();
for(;!isdigit(c);c=getchar())if(c=='-')f=-1;
for(;isdigit(c);c=getchar())x=(x<<1)+(x<<3)+c-'0';
x*=f;
}
int n,m,q;
int dfn[N],low[N],dfsxu,col[N],siz[N],dcc;
int fa[N],rt;
int f[N][20],dep[N];
ll g[N][20],h[N][20],ans;
bool bridge[N<<1];
int find(int x){
if(fa[x]==x)return x;
return fa[x]=find(fa[x]);
}
void merge(int x,int y){
fa[find(x)]=find(y);
}
struct graph{
int head[N],cnt;
graph(){
memset(head,-1,sizeof(head));
cnt=1;
}
struct Edge{
int to,next;
}e[N<<1];
void add(int x,int y){
e[++cnt]=(Edge){y,head[x]},head[x]=cnt;
}
}g1,g2;
void tarjan(int u,int fa){
dfn[u]=low[u]=++dfsxu;
bool flag=false;
for(int i=g1.head[u];~i;i=g1.e[i].next){
int v=g1.e[i].to;
if(!dfn[v]){
tarjan(v,u);
low[u]=min(low[u],low[v]);
if(dfn[u]<low[v])
bridge[i]=bridge[i^1]=true;
}
else if(v!=fa||flag)low[u]=min(low[u],dfn[v]);
else flag=true;
}
}
void dfs1(int u){
col[u]=dcc;
siz[dcc]++;
for(int i=g1.head[u];~i;i=g1.e[i].next){
int v=g1.e[i].to;
if(col[v]||bridge[i])continue;
dfs1(v);
}
}
void dfs2(int u,int fa){
dep[u]=dep[fa]+1;
f[u][0]=fa;
g[u][0]=siz[u];
h[u][0]=1ll*siz[u]*siz[u];
Rep(i,1,19){
f[u][i]=f[f[u][i-1]][i-1];
g[u][i]=g[u][i-1]+g[f[u][i-1]][i-1];
h[u][i]=h[u][i-1]+h[f[u][i-1]][i-1];
}
for(int i=g2.head[u];~i;i=g2.e[i].next){
int v=g2.e[i].to;
if(v==fa)continue;
dfs2(v,u);
}
}
ll lca(int x,int y){
ll ans1=0,ans2=0;
if(dep[x]<dep[y])swap(x,y);
_Rep(i,19,0)
if(dep[f[x][i]]>=dep[y]){
ans1+=g[x][i];
ans2+=h[x][i];
x=f[x][i];
}
if(x==y){
ans1+=siz[x];
ans2+=1ll*siz[x]*siz[x];
return ans1*ans1-ans2;
}
_Rep(i,19,0)
if(f[x][i]!=f[y][i]){
ans1+=g[x][i];
ans2+=h[x][i];
ans1+=g[y][i];
ans2+=h[y][i];
x=f[x][i],y=f[y][i];
}
ans1+=g[x][0],ans2+=h[x][0];
ans1+=g[y][0],ans2+=h[y][0];
ans1+=siz[f[x][0]],ans2+=1ll*siz[f[x][0]]*siz[f[x][0]];
return ans1*ans1-ans2;
}
int main()
{
freopen("map.in","r",stdin);
freopen("map.out","w",stdout);
read(n),read(m),read(q);
Rep(i,1,m){
int x,y;
read(x),read(y);
g1.add(x,y),g1.add(y,x);
}
Rep(i,1,n)if(!dfn[i])tarjan(i,i);
Rep(i,1,n)if(!col[i])dcc++,dfs1(i);
Rep(i,1,dcc)fa[i]=i;
Rep(i,2,g1.cnt)
if(bridge[i]){
int u=g1.e[i].to,v=g1.e[i^1].to;
g2.add(col[u],col[v]);
merge(col[u],col[v]);
}
int rt=dcc+1;
Rep(i,1,dcc)if(fa[i]==i)g2.add(dcc+1,i),g2.add(i,dcc+1);
dfs2(1,0);
while(q--){
int x,y;
read(x),read(y);
if(find(col[x])==find(col[y]))ans+=lca(col[x],col[y]);
}
printf("%lld\n",ans);
return 0;
}