【loli的胡策】NOIP训练8.10(数论+树形dp+贪心)

来源:互联网 发布:淘宝卖家发货扫描单号 编辑:程序博客网 时间:2024/04/28 23:56

这里写图片描述
题解:
贝祖定理:若设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 2000005using 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]);}

这里写图片描述
这里写图片描述
题解:挖坑待填

阅读全文
0 0
原创粉丝点击