Codeforces Round #485 Div. 1 vp记

  A:对每种商品多源bfs一下每个点到该商品的最近距离,对每个点sort一下取前s个即可。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define int long long
#define N 100010
int n,m,k,s,a[N],p[N],d[110][N],b[110],q[N],t;
int read()
{
    int x=0,f=1;char c=getchar();
    while (c<‘0‘||c>‘9‘) {if (c==‘-‘) f=-1;c=getchar();}
    while (c>=‘0‘&&c<=‘9‘) x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x*f;
}
struct data{int to,nxt;
}edge[N<<1];
void addedge(int x,int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;}
void bfs(int k)
{
    int head=0,tail=0;memset(d[k],42,sizeof(d[k]));
    for (int i=1;i<=n;i++) if (a[i]==k) q[++tail]=i,d[k][i]=0;
    do
    {
        int x=q[++head];
        for (int i=p[x];i;i=edge[i].nxt)
        if (d[k][edge[i].to]>d[k][x])
        {
            d[k][edge[i].to]=d[k][x]+1;
            q[++tail]=edge[i].to;
        }
    }while (head<tail);
}
signed main()
{
#ifndef ONLINE_JUDGE
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
#endif
    n=read(),m=read(),k=read(),s=read();
    for (int i=1;i<=n;i++) a[i]=read();
    for (int i=1;i<=m;i++)
    {
        int x=read(),y=read();
        addedge(x,y),addedge(y,x);
    }
    for (int i=1;i<=k;i++) bfs(i);
    for (int i=1;i<=n;i++)
    {
        for (int j=1;j<=k;j++) b[j]=d[j][i];
        sort(b+1,b+k+1);
        int ans=0;
        for (int j=1;j<=s;j++) ans+=b[j];
        printf("%d ",ans);
    }
    return 0;
}

  B:看起来非常玄乎事实上只是说两人交换次数的奇偶性不同。考虑将原排列变成该排列的最小交换次数,也即n-置换的循环节,这个东西的奇偶性是与交换次数的奇偶性有关的,因为每次交换会合并或拆开置换的两个循环。或者可以发现逆序对的奇偶性也是与其相关的,因为显然交换只会对两位置之间的区间产生影响,如果之间的数比两位置上的数都小或都大显然没有影响,否则每有一个这样的数逆序对变化两个。同时两位置本身带来一个逆序对变化,这样总逆序对变化量肯定是奇数。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define N 1000010
int read()
{
    int x=0,f=1;char c=getchar();
    while (c<‘0‘||c>‘9‘) {if (c==‘-‘) f=-1;c=getchar();}
    while (c>=‘0‘&&c<=‘9‘) x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x*f;
}
int n,a[N];
bool flag[N];
ll s;
signed main()
{
#ifndef ONLINE_JUDGE
    freopen("b.in","r",stdin);
    freopen("b.out","w",stdout);
#endif
    n=read();
    for (int i=1;i<=n;i++) a[i]=read();
    int c=n;
    for (int i=1;i<=n;i++)
    if (!flag[i])
    {
        c--;flag[i]=1;
        int x=a[i];while (!flag[x]) flag[x]=1,x=a[x];
    }
    if ((c&1))
    {
        if (n&1) cout<<"Petr";else cout<<"Um_nik";
    }
    else
    {
        if (n&1) cout<<"Um_nik";else cout<<"Petr";
    }
    return 0;
}

  1.5h之后C还是没有思路,自闭到结束。

  result:rank 154

  C:刚的过程中最接近正解的想法是对0~2n-1建一些辅助点,对每个点将每一位挖掉与其连边,然后将辅助节点取反后连边,但这样显然不对。事实上稍加(?)修改就行了。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define N (1<<22)
int read()
{
    int x=0,f=1;char c=getchar();
    while (c<‘0‘||c>‘9‘) {if (c==‘-‘) f=-1;c=getchar();}
    while (c>=‘0‘&&c<=‘9‘) x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x*f;
}
int n,m,a[N],b[N],ans;
bool flag[N<<1];
void dfs(int k)
{
    flag[k]=1;
    if (k>(1<<m))
    {
        if (!flag[a[k^(1<<m)]]) dfs(a[k^(1<<m)]);
    }
    else
    {
        for (int i=0;i<m;i++)
        if (!(k&(1<<i))&&!flag[k|(1<<i)]) dfs(k|(1<<i));
        if (b[k^(1<<m)-1]&&!flag[b[k^(1<<m)-1]+(1<<m)]) dfs(b[k^(1<<m)-1]+(1<<m));
    }
}
signed main()
{
#ifndef ONLINE_JUDGE
    freopen("c.in","r",stdin);
    freopen("c.out","w",stdout);
#endif
    m=read(),n=read();
    for (int i=1;i<=n;i++) b[a[i]=read()]=i;
    for (int i=(1<<m)+1;i<=(1<<m)+n;i++)
    if (!flag[i]) dfs(i),ans++;
    cout<<ans;
    return 0;
}

  D:题意莫名其妙,实际上是设f(x)为x所有分解因子方式中最小的因子和,求f(x) (x>=n)的最小值。一个古老的结论是因子之和固定时尽量取3能使乘积最大,有剩余时补2,于是只需考虑这样的数。求对数可以大致求出答案范围。枚举每一种可能,高精度求出即可。这需要多项式快速幂。于是就被各种问题折腾了一天。有多惨我已经不想回顾了,最后也不知道怎么过的。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define N (1<<19)
#define M 1500010
int read()
{
    int x=0,f=1;char c=getchar();
    while (c<‘0‘||c>‘9‘) {if (c==‘-‘) f=-1;c=getchar();}
    while (c>=‘0‘&&c<=‘9‘) x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x*f;
}
int n,a[M],r[N],len,ans=100000000;
ll f[N],c[N];
char s[M];
const double PI=3.14159265358979323846;
struct complex
{
    double x,y;
    complex operator +(const complex&a) const
    {
        return (complex){x+a.x,y+a.y};
    }
    complex operator -(const complex&a) const
    {
        return (complex){x-a.x,y-a.y};
    }
    complex operator *(const complex&a) const
    {
        return (complex){x*a.x-y*a.y,x*a.y+y*a.x};
    }
}g[N],b[N];
void DFT(complex *a,int n,int op)
{
    for (int i=0;i<n;i++) if (i<r[i]) swap(a[i],a[r[i]]);
    for (int i=2;i<=n;i<<=1)
    {
        complex wn=(complex){cos(2*PI/i),op*sin(2*PI/i)};
        for (int j=0;j<n;j+=i)
        {
            complex w=(complex){1,0};
            for (int k=j;k<j+(i>>1);k++,w=w*wn)
            {
                complex x=a[k],y=w*a[k+(i>>1)];
                a[k]=x+y,a[k+(i>>1)]=x-y;
            }
        }
    }
}
int work(int n,int c)
{
    c*=pow(3,n%6);n/=6;
    memset(f,0,sizeof(f));memset(b,0,sizeof(b));memset(g,0,sizeof(g));
    g[0].x=1;b[0].x=729;int t;
    for (t=2;t<=(n<<1);t<<=1)
    {
        for (int i=0;i<t;i++) r[i]=(r[i>>1]>>1)|(i&1)*(t>>1);
        DFT(b,t,1);
        if (n&(t>>1))
        {
            DFT(g,t,1);
            for (int i=0;i<t;i++) g[i]=g[i]*b[i];
            DFT(g,t,-1);
            for (int i=0;i<t;i++) f[i]=g[i].x/t+0.5;
            for (int i=0;i<t;i++) if (f[i]>999) f[i+1]+=f[i]/1000,f[i]%=1000;
            for (int i=0;i<t;i++) g[i].x=f[i],g[i].y=0;
        }
        if (t>n) break;
        for (int i=0;i<t;i++) b[i]=b[i]*b[i];
        DFT(b,t,-1);
        for (int i=0;i<t;i++) f[i]=b[i].x/t+0.5;
        for (int i=0;i<t;i++) if (f[i]>999) f[i+1]+=f[i]/1000,f[i]%=1000;
        for (int i=0;i<t;i++) b[i].x=f[i],b[i].y=0;
    }
    for (int i=0;i<t;i++) f[i]=g[i].x;
    for (int i=0;i<t;i++) f[i]=f[i]*c;
    for (int i=0;i<t;i++) if (f[i]>999) f[i+1]+=f[i]/1000,f[i]%=1000;
    while (f[t]==0) t--;return t+1;
    //c*729^n
}
int mul(ll *f,int c)
{
    int n=N-1;while (f[n]==0) n--;
    for (int i=0;i<=n;i++) f[i]*=c;
    for (int i=0;i<=n;i++) f[i+1]+=f[i]/1000,f[i]%=1000;
    if (f[n+1]) n++;
    return n+1;
}
bool check(ll *f,int len)
{
    int m=(n-1)/3+1;
    if (len>m) return 1;
    if (len<m) return 0;
    for (int i=m-1;~i;i--)
    if (f[i]!=a[i]) return f[i]>a[i];
    return 1;
}
signed main()
{
#ifndef ONLINE_JUDGE
    freopen("d.in","r",stdin);
    freopen("d.out","w",stdout);
#endif
    scanf("%s",s+1);n=strlen(s+1);
    for (int i=0;i<n;i++) a[i]=s[n-i]-‘0‘;
    if (n==1&&a[0]==1) {cout<<1;return 0;}
    for (int i=0;i<(n-1)/3+1;i++) a[i]=a[i*3]+a[i*3+1]*10+a[i*3+2]*100;
    len=work(max(floor((n-1)/log10(3))-1,0.0),1);
    for (int k=max(floor((n-1)/log10(3))-1,0.0);k<=ceil(n/log10(3))+1;k++)
    {
        memcpy(c,f,sizeof(c));
        if (check(c,len)) {ans=min(ans,k*3);break;}
        if (check(c,mul(c,2))) {ans=min(ans,k*3+2);break;}
        if (check(c,mul(c,2))) {ans=min(ans,k*3+4);}
        len=mul(f,3);
    }
    cout<<ans;
    return 0;
}

  E:先考虑序列上怎么做。考虑每种质因子,问题变为求区间每个数和x取min之和。显然每个数的质因子数量不会很多,所以对每种质因子个数分别建个BIT即可,复杂度即为log2。可以线性筛预处理做到log分解质因数。树上问题直接树剖的话是log3,不太能接受,可以通过欧拉序去一个log,即在进入子树时加,退出子树时减。我又被,卡常了。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
#define ll long long
#define N 100010
#define M 10000000
#define P 1000000007
int read()
{
    int x=0,f=1;char c=getchar();
    while (c<‘0‘||c>‘9‘) {if (c==‘-‘) f=-1;c=getchar();}
    while (c>=‘0‘&&c<=‘9‘) x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x*f;
}
int n,p[N],a[N],prime[M+10],minp[M+10],deep[N],fa[N][20],in[N],out[N],ans[N],tree[30][N<<1],cnt,m,t;
bool flag[M+10],tmp[30];
struct data{int to,nxt;
}edge[N<<1];
struct data2{int x,y,z,lca;
}q[N];
struct data3{int x,cnt;};
vector<data3> point[M+10],Q[M+10];
void addedge(int x,int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;}
void add(int p,int k,int x){while (k<=2*n) tree[p][k]+=x,k+=k&-k;}
int query(int p,int k){int s=0;while (k) s+=tree[p][k],k-=k&-k;return s;}
int ksm(int a,int k)
{
    int s=1;
    for (;k;k>>=1,a=1ll*a*a%P) if (k&1) s=1ll*s*a%P;
    return s;
}
void dfs(int k)
{
    in[k]=out[k]=++cnt;
    for (int i=p[k];i;i=edge[i].nxt)
    if (edge[i].to!=fa[k][0])
    {
        fa[edge[i].to][0]=k;
        deep[edge[i].to]=deep[k]+1;
        dfs(edge[i].to);
        out[k]=++cnt;
    }
}
int lca(int x,int y)
{
    if (deep[x]<deep[y]) swap(x,y);
    for (int j=19;~j;j--) if (deep[fa[x][j]]>=deep[y]) x=fa[x][j];
    if (x==y) return x;
    for (int j=19;~j;j--) if (fa[x][j]!=fa[y][j]) x=fa[x][j],y=fa[y][j];
    return fa[x][0];
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("e.in","r",stdin);
    freopen("e.out","w",stdout);
#endif
    flag[1]=1;cnt=0;
    for (int i=2;i<=M;i++)
    {
        if (!flag[i]) prime[++cnt]=i,minp[i]=i;
        for (int j=1;j<=cnt&&prime[j]*i<=M;j++)
        {
            flag[prime[j]*i]=1;
            minp[prime[j]*i]=prime[j];
            if (i%prime[j]==0) break;
        }
    }
    n=read();
    for (int i=1;i<n;i++)
    {
        int x=read(),y=read();
        addedge(x,y),addedge(y,x);
    }
    cnt=0;dfs(1);
    fa[1][0]=1;
    for (int j=1;j<20;j++)
        for (int i=1;i<=n;i++)
        fa[i][j]=fa[fa[i][j-1]][j-1];
    for (int i=1;i<=n;i++)
    {
        int x=a[i]=read();
        while (x>1)
        {
            int y=minp[x],cnt=0;
            while (minp[x]==y) cnt++,x/=y;
            point[y].push_back((data3){i,cnt});
        }
    }
    m=read();cnt=0;
    for (int i=1;i<=m;i++)
    {
        q[i].x=read(),q[i].y=read(),q[i].z=read();q[i].lca=lca(q[i].x,q[i].y);ans[i]=1;
        int x=q[i].z;
        while (x>1)
        {
            int y=minp[x],cnt=0;
            while (minp[x]==y) cnt++,x/=y;
            Q[y].push_back((data3){i,cnt});
        }
    }
    fa[1][0]=0;
    int u=25;
    for (int i=1;i<=M;i++)
    if (!flag[i])
    {
        while (ksm(i,u)>M) u--;
        for (int j=0;j<point[i].size();j++)
        {
            add(point[i][j].cnt,in[point[i][j].x],1);
            add(point[i][j].cnt,out[point[i][j].x]+1,-1);
            tmp[point[i][j].cnt]=1;
        }
        for (int j=0;j<Q[i].size();j++)
        {
            ll x=0;
            for (int k=1;k<=Q[i][j].cnt;k++)
            if (tmp[k]) x+=k*(query(k,in[q[Q[i][j].x].x])+query(k,in[q[Q[i][j].x].y])+
            1ll*(P-2)*query(k,in[q[Q[i][j].x].lca])%(P-1)+1ll*(P-2)*query(k,in[fa[q[Q[i][j].x].lca][0]])%(P-1));
            for (int k=Q[i][j].cnt+1;k<=u;k++)
            if (tmp[k]) x+=Q[i][j].cnt*(query(k,in[q[Q[i][j].x].x])+query(k,in[q[Q[i][j].x].y])+
            1ll*(P-2)*query(k,in[q[Q[i][j].x].lca])%(P-1)+1ll*(P-2)*query(k,in[fa[q[Q[i][j].x].lca][0]])%(P-1));
            ans[Q[i][j].x]=1ll*ans[Q[i][j].x]*ksm(i,((x%(P-1))+P-1)%(P-1))%P;
        }
        for (int j=0;j<point[i].size();j++)
        {
            add(point[i][j].cnt,in[point[i][j].x],-1);
            add(point[i][j].cnt,out[point[i][j].x]+1,1);
            tmp[point[i][j].cnt]=0;
        }
    }
    for (int i=1;i<=m;i++) printf("%d\n",ans[i]);
    return 0;
}

原文地址:https://www.cnblogs.com/Gloid/p/10211755.html

时间: 2024-10-02 18:45:16

Codeforces Round #485 Div. 1 vp记的相关文章

Codeforces Round #485 (Div. 2) E. Petr and Permutations

Codeforces Round #485 (Div. 2) E. Petr and Permutations 题目连接: http://codeforces.com/contest/987/problem/E Description Petr likes to come up with problems about randomly generated data. This time problem is about random permutation. He decided to gene

Codeforces Round #485 (Div. 2) D. Fair

Codeforces Round #485 (Div. 2) D. Fair 题目连接: http://codeforces.com/contest/987/problem/D Description Some company is going to hold a fair in Byteland. There are $n$ towns in Byteland and $m$ two-way roads between towns. Of course, you can reach any t

【思维】Codeforces Round #485 (Div. 2) B. High School: Become Human(对数)

题目链接:http://codeforces.com/contest/987/problem/B 在运算的时候取对数就好了 1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 #define ll long long 6 #define eps 1e-6 7 8 int main() 9 { 10 ll x,y; 11 double xx; 12 scanf("%lld %lld",&x,&y);

Codeforces Round#500 Div.2 翻车记

A:签到 #include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=

Codeforces Round #485 (Div. 2)

A. Infinity Gauntlet time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output You took a peek on Thanos wearing Infinity Gauntlet. In the Gauntlet there is a place for six Infinity Gems: the Power G

Codeforces Round #485 (Div. 2) C Three displays

C. Three displays It is the middle of 2018 and Maria Stepanovna, who lives outside Krasnokamensk (a town in Zabaikalsky region), wants to rent three displays to highlight an important problem. There are nn displays placed along a road, and the ii-th

Codeforces Round #485 (Div. 2)-B-High School: Become Human

B. High School: Become Human time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output Year 2118. Androids are in mass production for decades now, and they do all the work for humans. But androids ha

Codeforces Round#509 Div.2翻车记

A:签到 #include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=

Codeforces Round #535 (Div. 3)小上分记

Codeforces Round #535 (Div. 3)小上分记 前言 被拉去买新年衣服了,导致半小时后才进场. 虽然做了4道题,但是rating还是涨得不多. 用predictor看了rating变化后心灰意冷,不看E题了. A ...800的难度. B 本来还在想要不要用什么STL.后来发现直接用桶就行了.然后就可以水过了. C 题意差点理解不了. 就6种情况都去考虑一下,找最小代价的即可.不要考虑少了. 每次都是\(O(n)\)的,所以能搞. D 贪心地换字母即可. E 坑.待填. 原