题解:
贝祖定理:若设a,b是整数,则存在整数x,y,使得ax+by=gcd(a,b),那么我们可以知道如果 c不是gcd(m,n)的倍数,那么一定不是好的(虽然与我的算法无关,但还是说一下)
好了其实我的算法是—-暴力
代码:
#include <cstdio>
#include <cmath>
#include <iostream>
#define LL long long
using namespace std;
int n,m;LL q;
int gcd(int a,int b){return b?gcd(b,a%b):a;}
int main()
{
int T,i,j;
scanf("%d",&T);
while (T--)
{
scanf("%d%d%lld",&n,&m,&q);
LL ans=q;
if (n>m) swap(n,m);
int minn=n,maxx=m;
int gg=gcd(maxx,minn);
n/=gg; m/=gg; q/=gg;
ans-=q/m+q/n-q/(n*m);
for (i=1;i<minn;i++)
if (q<i*m) break;
else ans-=(q-i*m)/n-(q-i*m)/(m*n);
printf("%lld\n",ans);
}
}
题解:
考场30pts暴力
这道题可以考虑枚举最大公因数,然后求最大公因数为i的最长链。我们考虑将每条边拆成因数条边,要是一次性加入的话数量会炸飞,所以我们每次将是当前公因数倍数的边加入,然后求树上的最长链,然后用当前的公因数更新长度为最长链的长度的答案。求解后将数组清0,重复利用有些长度不可能出现在最长链中,因为他是构成最长链的一部分,所以如果这个长度的答案<长度大于它的答案的话,就要将长度大于他的答案给他,从大到小枚举ans[i]=max(ans[i],ans[i+1]);
代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#define N 800005
#define Q 2000005
using namespace std;
int cnt,tot,nxtt[N],head[Q],x[N],y[N],nxt[N],point[N],v[N],sz,dian[N],d,vis[N],len,a[N];
void addquan(int z,int xx,int yy)
{
++cnt; nxtt[cnt]=head[z]; head[z]=cnt; x[cnt]=xx; y[cnt]=yy;
}
void addline(int x,int y)
{
++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y;
++tot; nxt[tot]=point[y]; point[y]=tot; v[tot]=x;
dian[++d]=x; dian[++d]=y;
}
int dfs(int x,int fa)
{
vis[x]=sz;
int m1,m2; m1=m2=0;
for (int i=point[x];i;i=nxt[i])
if (v[i]!=fa)
{
int l=dfs(v[i],x);
if (l+1>m1) m2=m1,m1=l+1;
else m2=max(m2,l+1);
}
len=max(m1+m2,len);
return m1;
}
int main()
{
freopen("walk.in","r",stdin);
freopen("walk.out","w",stdout);
int n,i,j,ys;
scanf("%d",&n);
for (i=1;i<n;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
addquan(c,a,b);
}
for (ys=1;ys<=100000;ys++)//枚举公因数
{
for (j=ys;j<=100000;j+=ys)
for (i=head[j];i;i=nxtt[i])
addline(x[i],y[i]);
++sz;len=0;
for (i=1;i<=d;i++)
if (vis[dian[i]]!=sz) dfs(dian[i],0);
a[len]=ys;
d=0;tot=0;memset(point,0,sizeof(point));
}
for (i=n;i>=1;i--) a[i]=max(a[i],a[i+1]);
for (i=1;i<=n;i++)
printf("%d\n",a[i]);
}
题解:挖坑待填