【牛客网】【埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛】B—合约数【莫队做法】

143人阅读 评论(0) 收藏 举报
分类:

题目链接:B—合约数

题意:一棵树,有n个节点,从1编号到n。根节点的编号为p。给出每个节点的val[i]值,定义f(i)为以编号i为根节点的子树中(包括根节点),所有val[j]是合数并且是val[i]的约数的节点个数。求所有f(i)的和。答案对1e9+7取模。

题解:学长说可以用set的启发式合并或者splay的启发式合并。emmm,我太菜了不会这些怎么写。我的做法是:预处理范围内的数字是否是合数,然后对1-10000的数字用vector数组存下各自的因数。然后用dfs序,将各子树变成一个区间问题,用莫队算法解决。n是20000,每个数字不超过10000,这样复杂度就是 20000*(200+约数的个数,没几十个)。

ac代码:

#include<iostream>
#include<stdio.h>
#include<string>
#include<string.h>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
#include<set>
#include<map>
#include<math.h>
using namespace std;
int val[20000+10];
int block;
int caz=0;
long long mod =1000000007;
int vis[20000+10];
int cishu[20000+10];
int num[20000+10];
int notprime[20000+10];
int prime[20000+10];
vector<int> vt[10000+10];
int cnt=0;
struct Query
{
    int l,r,pos;
}query[20000+10];
bool cmp(Query a,Query b)
{
    if(a.l/block!=b.l/block){
        return a.l<b.l;
    }
    return a.r<b.r;
}
struct Node
{
    int v,nne;
}node[40000+10];
int head[20000+10];
void build(int u,int v)
{
    node[cnt].v=v;
    node[cnt].nne=head[u];
    head[u]=cnt++;
}
void dfs(int rt)
{
    vis[rt]=caz;
    num[++cnt]=val[rt];
    query[rt].l=cnt;
    query[rt].pos=rt;
    for(int i=head[rt];i;i=node[i].nne){
        if(vis[node[i].v]<caz){
            dfs(node[i].v);
        }
    }
    query[rt].r=cnt;
}
int main()
{
    int t,n,p;
    //prime
    for(int i=2;i<=20000;i++){
        if(notprime[i]==0){
            prime[cnt++]=i;
        }
        for(int j=0;j<cnt&&prime[j]*i<=20000;j++){
            notprime[i*prime[j]]=1;
            if(i%prime[j]==0) break;
        }
    }
    //
    for(int i=1;i<=10000;i++){
        if(notprime[i]){
            double sq=sqrt(i);
            for(int j=1;j<=sq;j++){
                if(i%j==0){
                    if(notprime[j])vt[i].push_back(j);
                    if(notprime[i/j]&&i/j!=j)vt[i].push_back(i/j);
                }
            }
        }
    }
    //
    scanf("%d",&t);
    while(t--){
        long long ans=0,temp=0;
        scanf("%d%d",&n,&p);
        block=(int)sqrt(n);
        memset(cishu,0,sizeof(cishu));
        memset(head,0,sizeof(head));
        caz++;
        cnt=1;
        int a,b;
        for(int i=1;i<n;i++){
            scanf("%d%d",&a,&b);
            build(a,b);
            build(b,a);
        }
        for(int i=1;i<=n;i++){
            scanf("%d",&val[i]);
        }
        cnt=0;
        dfs(p);
        sort(query+1,query+1+n,cmp);

        int L=query[1].l,R=query[1].r;
        for(int i=L;i<=R;i++){
            cishu[num[i]]++;
        }
        temp=0;
        vector<int>::iterator it=vt[val[query[1].pos]].begin();
        for(;it!=vt[val[query[1].pos]].end();++it){
            temp+=cishu[*it];
        }
        ans=(ans+temp*query[1].pos%mod)%mod;
        printf("%lld\n",ans);
        for(int i=2;i<=n;i++){
            if(query[i].l>L){
                while(query[i].l>L){
                    cishu[num[L]]--;
                    L++;
                }
            }
            else if(query[i].l<L){
                while(query[i].l<L){
                    L--;
                    cishu[num[L]]++;
                }
            }

            if(query[i].r>R){
                while(query[i].r>R){
                    R++;
                    cishu[num[R]]++;
                }
            }
            else if(query[i].r<R){
                while(query[i].r<R){
                    cishu[num[R]]--;
                    R--;
                }
            }
            temp=0;
            for(it=vt[val[query[i].pos]].begin();it!=vt[val[query[i].pos]].end();it++){
                temp+=cishu[*it];
            }
            ans=(ans+temp*query[i].pos%mod)%mod;
            printf("%lld %lld\n",temp,ans);
        }
        printf("%lld\n",ans);
    }

}

查看评论

编程方向

 一、前言  很多人认为,数据库编程是一个颇具诱惑力的工作,这诱惑力来自于数据库应用的巨大市场需求。计算机应用有科学计算、数据处理与过程控制三大主要领域,而数据处理是其中所占比重最大的一个领域,包括现...
  • xingjiaren
  • xingjiaren
  • 2001-04-10 11:37:00
  • 937

第15届上海大学程序设计联赛夏季赛暨上海高校金马五校赛(部分题解)

唉,好久没更新博客了,说明我这段时间在学习上都懈怠了Σ( ° △ °|||)︴昨天打了场金马赛,这网络…..我真的是无力吐槽…..前三题都是大水题,就不挂代码了;D-快速幂取模裸题#include u...
  • Murphyc
  • Murphyc
  • 2017-07-10 13:54:47
  • 484

埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛

五题菜狗… 那个自习室真是有毒..坐了一下子马上就感冒了..头痛… A Wasserstein Distance 这题也是搞不懂,一开始狂wa,迷迷糊糊的. #include &amp;lt;...
  • m0_37802215
  • m0_37802215
  • 2018-04-15 20:09:09
  • 139

【牛客网】【埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛】L—K序列【动态规划】

题目链接:L—K序列题解:for一遍数组,temp[i]表示:不包括当前for到的点,序列和为i的最长长度。然后for一遍0-k,对dp[ (j+num[i])%k ]进行更新,dp[j]是包括当前点...
  • gymgym1212
  • gymgym1212
  • 2018-04-15 18:46:39
  • 181

埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛F题 1+2=3?

题目链接:https://www.nowcoder.com/acm/contest/91/F题意:求第N个符合条件X^2X=3X的X。N&amp;lt;=10的12次方。解题思路:我刚开始想到最粗暴的...
  • weixin_36416680
  • weixin_36416680
  • 2018-04-16 11:01:00
  • 61

埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛 F-1+2=3?

链接:https://www.nowcoder.com/acm/contest/91/F来源:牛客网题目描述 小Y在研究数字的时候,发现了一个神奇的等式方程,他屈指算了一下有很多正整数x满足这个等式...
  • albertluf
  • albertluf
  • 2018-04-15 16:46:44
  • 138

埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛 A-Wasserstein Distance

埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛 A-Wasserstein Distance链接:https://www.nowcoder.com/acm/contest/91/A来源...
  • gdut_yy
  • gdut_yy
  • 2018-04-16 11:22:06
  • 9

埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛H题小Y与多米诺骨牌(线段树优化dp)

题意 题目链接:https://www.nowcoder.com/acm/contest/91/H 来源:牛客网 题解 设l[i]l[i]l[i]为向左推第iii个骨牌最远能影响到的骨牌的...
  • ME495
  • ME495
  • 2018-04-17 11:20:36
  • 92

埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛 J-小Y写文章(二分+二分图匹配)

链接:https://www.nowcoder.com/acm/contest/91/J来源:牛客网题目描述 小Y写了一篇文章,他对自己的文笔很有自信,尤其是自己总结出了一套计算文章通顺性的公式。 ...
  • albertluf
  • albertluf
  • 2018-04-18 10:27:07
  • 106

埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛 L K序列

题目: 给一个数组 a,长度为 n,若某个子序列中的和为 K 的倍数,那么这个序列被称为“K 序列”。现在要你 对数组 a 求出最长的子序列的长度,满足这个序列是 K 序列。 Input: 第...
  • Tony5t4rk
  • Tony5t4rk
  • 2018-04-16 19:42:25
  • 13
    个人资料
    等级:
    访问量: 391
    积分: 33
    排名: 195万+
    文章分类
    文章存档