【Author : DS && MZ】2012 金华网络预赛 Chapter 2

比赛总结 专栏收录该内容
22 篇文章 0 订阅

1008 数论

因为 < 400000最多有7种不同的质因数

Operator 1 : 用容斥原理计算出[l , r] 里面与p互质的数的和。 遍历前面的Operator 2 操作,如果在区间内则修改。

修改的时候,判断原数是否与p互质,新数是否与p互质,加减操作。

Operator 2 : 将操作放在Vector里面,并用一个Map记录x

const LL PRIMERANGE = 400001;
int prime[PRIMERANGE + 1];
int getPrime()
{
    memset (prime, 0, sizeof (int) * (PRIMERANGE + 1));
    for (int i = 2; i <= PRIMERANGE; i++)
    {
        if (!prime[i]) prime[++prime[0]] = i;
        for (int j = 1; j <= prime[0] && prime[j] <= PRIMERANGE / i; j++)
        {
            prime[prime[j]*i] = 1;
            if (i % prime[j] == 0) break;
        }
    }
    return prime[0];
}

int factor[100][3], facCnt;
int getFactors(int x)
{
    facCnt = 0;
    int tmp = x;
    for(int i = 1; prime[i] <= tmp / prime[i]; i++)
    {
        factor[facCnt][1] = 1, factor[facCnt][2] = 0;
        if(tmp % prime[i] == 0)
            factor[facCnt][0] = prime[i];
        while(tmp % prime[i] == 0)
            factor[facCnt][2]++, factor[facCnt][1] *= prime[i], tmp /= prime[i];
        if(factor[facCnt][1] > 1) facCnt++;
    }
    if(tmp != 1)
        factor[facCnt][0] = tmp, factor[facCnt][1] = tmp, factor[facCnt++][2] = 1;
    return facCnt;
}
LL getmz(LL nn , LL pp){
    LL res = nn / pp;
    res = res * (res + 1LL) / 2LL;
    return res * pp;
}
LL getds(LL nn , LL pp){
    getFactors(pp);
    LL ans = 0;
    LL alll = 1LL << facCnt;
    for (int i = 0 ; i < alll ; ++i){
        int temp = 0 ; LL tempsum = 1;
        int ii = i;
        for (int j = 0 ; j < facCnt && ii ; ++j){
            if (ii & 1){
                temp ++;
                tempsum *= factor[j][0];
            }
            ii >>= 1;
        }
        //cout << tempsum << endl;
        if (temp & 1) ans-=getmz( nn , tempsum);
        else ans+= getmz(nn ,tempsum);
    }
    return ans;
}
int gcd(int a,int b)
{
    return b?gcd(b,a%b):a;
}
int n , m;
map<LL , LL> mem;
map<int , int> :: iterator iter;
vector< pair<int , LL> > mz;
void solve(){
    mz.clear();
    mem.clear();
    scanf("%d%d" , &n, &m);
    while (m--){
        int op , x , y , z;
        scanf("%d",&op);
        if (op == 2){
            scanf("%d%d" , &x, &y);
            mz.push_back(make_pair(x , y));
            mem[x] = mz.size() - 1;
        }
        else{
            scanf("%d%d%d" , &x , &y , &z);
            LL ans = getds(y , z) - getds(x - 1, z);
            for (int i = 0 ; i < mz.size();++i){
                if (mem[mz[i].first] != i) continue;
                if (x <= mz[i].first && mz[i].first <=y){
                    LL now = mz[i].first;
                    if (gcd(now , z) == 1) ans -= now;
                    now = mz[i].second;
                    if (gcd(now , z) == 1) ans += now;
                }
            }
            printf("%I64d\n",ans);
        }
    }
}
int main(){
    int _;
    getPrime();
    cin >> _;
    while (_--) solve();
}

1010 裸LCA

Trick : 

root的兄弟有一个 ; 公共祖先的定义不同

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <map>
#include <string>
#include <cstring>
#include <cmath>
#define N 30100
#define M 1010
#define MP make_pair
#define PB push_back

using namespace std;
map<string,int> hash;
int n;
struct cong
{
    int gen;
    string name;
    int fa;
    int id;
    cong(){}
    cong (int a,string ss)
    {
        gen = a;
        name = ss;
    }
}s[N];
int r[N];
vector<int> son[N];
void init()
{
    hash.clear();
    memset(r,0,sizeof(r));
    for (int i=0;i<=n;i++) son[i].clear();
}
cong deal(char ss[M])
{
    int now = 0;
    int len = strlen(ss);
    int temp = 0;
    while (now<len)
    {
        if (ss[now++]=='.') temp++;
        else break;
    }
    string tt = "";
    for (int i=now-1;i<len;i++) tt+=ss[i];
    return cong(temp,tt);
}
void dfs(int k)
{
    //cout << "k = " << k << endl;
    for (int i=1;i<=s[k].gen;i++) printf("%c",'.');
    printf("%s\n",s[k].name.c_str());
    for (int i=0;i<son[k].size();i++)
    {
        dfs(son[k][i]);
    }
}
#define MAXN 100300
#define MAXL 20
struct ST
{
    int dat, loc;
    ST(int x, int y)
    {
        dat = x, loc = y;
    }
    ST(){}
}st[MAXN][MAXL];
int num[MAXN], p2[MAXL], h[MAXN], firstapp[MAXN];
void Format_ST()
{
    memset(st, 0, sizeof(st));
    p2[0] = 1;
    for (int i = 1; i < MAXL; ++i) p2[i] = p2[i - 1] * 2;
    for (int i = 1; i <= n; ++i) st[i][0] = ST(h[i], num[i]);
    for (int j = 1, p = 1; j < MAXL; ++j, p *= 2)
        for (int i = 1; i <= n - p * 2 + 1; ++i)
            if (st[i][j - 1].dat > st[i + p][j - 1].dat) st[i][j] = st[i][j - 1];
            else st[i][j] = st[i + p][j - 1];
}
ST RMQ(int s, int t)
{
    int l = (int)(log((double)(t - s + 1)) / log(2.0) + 1e-6);
    if (st[s][l].dat > st[t - p2[l] + 1][l].dat) return st[s][l];
    else return st[t - p2[l] + 1][l];
}
void make(int v, int deep)
{
    h[++n] = -deep;
    num[n] = v;
    for (int i = 0; i < son[v].size(); i++)
    {
        int y  =son[v][i];
        make(y, deep + 1);
        h[++n] = -deep;
        num[n] = v;
    }
}
bool cmp(int x,int y)
{
    return s[x].name<s[y].name;
}

int main()
{
    freopen("in.in","r",stdin);
    char ss[M],tt[M];
    while (scanf("%d\n",&n),n)
    {
        init();
        r[0] = 1;
        scanf("%s",ss);
        s[1] = cong(0,ss);
        hash[ss] = 1;
        s[1].fa = 0;
        s[1].id = 1;
        for (int i=2;i<=n;i++)
        {
            scanf("%s",ss);
            s[i] = deal(ss);
            s[i].id = i;
            hash[s[i].name] = i;
            s[i].fa = r[s[i].gen-1];
            r[s[i].gen] = i;
            son[s[i].fa].PB(i);
        }
        for (int i=1;i<=n;i++)
        {
            sort(son[i].begin(),son[i].end(),cmp);
        }

        //LCA
        n=0;
        make(1, 0);
        memset(firstapp,0,sizeof(firstapp));
        for (int i = 1; i <= n; ++i)
            if (!firstapp[num[i]]) firstapp[num[i]] = i;
        Format_ST();
        int m;
        scanf("%d\n",&m);
        while (m--)
        {
            scanf("%s",ss);
            if (ss[0]=='L')
            {
                dfs(1);
            }
            else if (ss[0]=='b')
            {
                scanf("%s",ss);
                if (hash[ss]==1) printf("1\n");
                else
                {
                    int fa = s[hash[ss]].fa;
                    printf("%d\n",son[fa].size());
                }
            }
            else
            {
                scanf("%s%s",ss,tt);
                int x = hash[ss];
                int y = hash[tt];
                int sx = firstapp[x], sy = firstapp[y];
                if (sx>sy) swap(sx,sy);
                int temp = RMQ(sx, sy).loc;
                if (temp==x || temp==y) printf("%s\n",s[s[temp].fa].name.c_str());
                else printf("%s\n", s[temp].name.c_str());
            }
        }
    }
    return 0;
}





  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

参与评论 您还未登录,请先 登录 后发表或查看评论
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页

打赏作者

ACM的记忆

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值