2017.10.2北京清北综合强化班DAY2

a
【问题描述】
你是能看到第一题的 friends呢。
                                                —— hja
世界上没有什么比卖的这 贵弹丸三还令人绝望事了,所以便么一道题。定义 ?(?)为满足 (?×?)|?的有序正整数对 (?,?)的个数。现在给定 ?,求 Σ?(?)??=1
【输入格式】
一行个整数 ?。
【输出格式】
一行个整数代表答案 。

【样例输入】
6
【样例输出】
25
【数据范围与规定】
对于 30%的数据, 1≤?≤100。
对于 60%的数据, 1≤?≤1000。
对于 100%的数据, 1≤?≤10^11。

 

题解:数论题

本以为写的O(n^3),结果过了60%的数据。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,ans;
int main(){
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=i;j++){
            if(i%j==0)
            for(int k=1;k<=j;k++){
                if(j%k==0)ans++;
            }
        }
    }
    cout<<ans<<endl;
    fclose(stdin);
    fclose(stdout);
    return 0;
}
60

 

正解:求sigema(i=1--n)f(i),对于f(x)为满足(a*b)|x,的点对个数。x为a*b的倍数,

假设这个倍数为c,那么a*b*c=x,所以对于sigema(i=1--n)f(i)实质上是求a*b*c<=x,

的点对个数,假设a<=b<=c,那么最后只要将结果×6,因为对于 1 2 3这个三个数

的数列的全排列有6个。a^3<=a*b*c<=n,那么a<=(n开三次方),所以a从1枚举到n

开三方,b从a+1枚举到根号下n/a,tmp累计答案。对于a*a*a它的全排列只有1个

,所以枚举的a,b,c不能重复,因为a*a*b,的全排列只有3个,所以也要去重。

这个时候枚举a,求b,看b有没有落在a的区间。

#include<cstdio>
#include<cstdlib>
#include<cstring>

using namespace std;

long long n;

#ifdef unix
#define LL "%lld"
#else
#define LL "%I64d"
#endif

int main() {
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);

    scanf(LL,&n);

    long long ans=0,tmp=0;

    for (long long a=1,v; a*a<=(v=n/a); a++,ans++)
        for (long long b=a+1; b*b<=v; b++)
            tmp+=n/(a*b)-b;
    ans+=tmp*6;
    tmp=0;
    for (long long a=1,v; (v=a*a)<=n; a++) {
        tmp+=n/v;
        if (a*a<=n/a) tmp--;
    }
    
    ans+=tmp*3;

    printf(LL "\n",ans);

    return 0;
}
AC

 

b
【问题描述】
你是能看到第二题的 friends呢。
                                            —— laekov
Hja和 Yjq为了 抢男主 角打了 起来 ,现在 他们 正在 一棵树 上决斗 。Hja在 A点,Yjq在 B点,Hja先发制人 开始 移动 。每次 他们 可以 沿着 一条边 移动 ,但 一旦 一条边 被对方 走过了 自己 就不能 再走这条边 了。每条 边上 都有 权值 ,他们 都希望 自己 的权值 尽量多 。现在 给你 这棵树 以及 他们 俩开始 的位置 ,问 Hja能 够获得 的最大权值 。
【输入格式】
第一行 两个 整数 ?,?,代表 树的点数 和询问 的个数 。
接下来 ?−1行每行 三个 整数 ?,?,?,代表 从?到?有一条 权值 为?的边 。
接下来 ?行,每行 两个整数 ?,?代表 一次 询问 。
【输出格式】
对于 每次 询问 ,输出 一个 整数 代表 答案 。
【样例输入1】
2 1
1 2 3
1 2
【样例输出1】 3
【样例输入2】
3 2
1 2 3
1
3 2 3
1 3
【样例输出2】

3

4

【数据范围与规定】
对于 30%的数据 ,1≤?,?≤1000。
对于另外 30%的数据 ,?=1。
对于 100%的数据, 1≤?,?≤105,0≤?≤103,1≤?,?,?,?≤?。

 

又是菊花图卡本萌妹QWQ

#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 100005
using namespace std;

int n,m,sumedge,a,b;
int head[maxn],size[maxn],dad[maxn],top[maxn],deep[maxn],fu[maxn],dis[maxn];

struct Edge{
    int x,y,z,nxt;
    Edge(int x=0,int y=0,int z=0,int nxt=0):
        x(x),y(y),z(z),nxt(nxt){}
}edge[maxn<<1];

void add(int x,int y,int z){
    edge[++sumedge]=Edge(x,y,z,head[x]);
    head[x]=sumedge;
}

void dfs(int x){
    size[x]=1;deep[x]=deep[dad[x]]+1;
    for(int i=head[x];i;i=edge[i].nxt){
        int v=edge[i].y;
        if(v==dad[x])continue;
        dad[v]=x;dis[v]=edge[i].z;
        dfs(v);
        size[x]+=size[v];
        fu[x]+=fu[v]+edge[i].z;
    }
}

void dfs_(int x){
    int s=0;
    if(!top[x])top[x]=x;
    for(int i=head[x];i;i=edge[i].nxt){
        int v=edge[i].y;
        if(v!=dad[x]&&size[v]>size[s])s=v;
    }
    if(s){
        top[s]=top[x];
        dfs_(s);
    }
    for(int i=head[x];i;i=edge[i].nxt){
        int v=edge[i].y;
        if(v!=dad[x]&&v!=s)dfs_(v);
    }
}

int lca(int x,int y){
    for(;top[x]!=top[y];){
        if(deep[top[x]]>deep[top[y]])swap(x,y);
        y=dad[top[y]];
    }
    if(deep[x]<deep[y])return x;
    return y;
}

void slove(int x,int y){
    int zx=lca(x,y);
    int lena=deep[x]-deep[zx],lenb=deep[y]-deep[zx];
    if(lena<lenb){
        int k=(lena+lenb)/2;
        for(int i=1;i<=k;i++)y=dad[y];
        printf("%d\n",fu[1]-fu[y]);
    }
    if(lena>lenb){
        int flag=0;
        int k=(lena+lenb)/2+(lena+lenb)%2;
        for(int i=1;i<=k;i++){
            if(dad[x]!=zx)x=dad[x];
            else {
                flag=1;
                printf("%d\n",fu[x]+dis[x]);
            }
        }
        if(flag==0)
        printf("%d\n",fu[x]);
    }
    if(lena==lenb){
        while(dad[y]!=zx)y=dad[y];
        printf("%d\n",fu[1]-fu[y]-dis[y]);
    }
}

int main(){
    freopen("b.in","r",stdin);
    freopen("b.out","w",stdout);
    scanf("%d%d",&n,&m);
    for(int i=1;i<n;i++){
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        add(x,y,z);add(y,x,z);
    }
    dfs(1);dfs_(1);
    for(int i=1;i<=m;i++){
        scanf("%d%d",&a,&b);
        slove(a,b);
    }
    fclose(stdin);
    fclose(stdout);
    return 0;
}
10

 

 

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>

using namespace std;

const int maxn=100010;

int n,m,en,z[maxn*3],f[maxn][20],q[maxn],depth[maxn],sum[maxn*3][2],fd[maxn],start[maxn],end[maxn],value[maxn];

struct edge
{
    int e,d;
    edge *next;
}*v[maxn],ed[maxn<<1];

void add_edge(int s,int e,int d)
{
    en++;
    ed[en].next=v[s];v[s]=ed+en;v[s]->e=e;v[s]->d=d;
}

int get(int p,int d)
{
    if (d==-1) return p;
    int x=0;
    while (d)
    {
        if (d&1) p=f[p][x];
        d>>=1;
        x++;
    }
    return p;
}

int get_lca(int p1,int p2)
{
    if (depth[p1]<depth[p2]) swap(p1,p2);
    p1=get(p1,depth[p1]-depth[p2]);
    int x=0;
    while (p1!=p2)
    {
        if (!x || f[p1][x]!=f[p2][x])
        {
            p1=f[p1][x];
            p2=f[p2][x];
            x++;
        }
        else x--;
    }
    return p1;
}

int calc(int p1,int p2)
{
    if (p1==f[p2][0]) return value[1]-value[p2];
    else return value[p1]+fd[p1];
}

int calcp(int p,int v)
{
    int l=start[p]-1,r=end[p];
    while (l+1!=r)
    {
        int m=(l+r)>>1;
        if (v>z[m]) l=m;
        else r=m;
    }
    return r;
}

int main()
{
    freopen("b.in","r",stdin);
    freopen("b.out","w",stdout);

    scanf("%d%d",&n,&m);
    int tot=0;
    for (int a=1;a<n;a++)
    {
        int s,e,d;
        scanf("%d%d%d",&s,&e,&d);
        tot+=d;
        add_edge(s,e,d);
        add_edge(e,s,d);
    }
    depth[1]=1;
    int front=1,tail=1;
    q[1]=1;
    for (;front<=tail;)
    {
        int now=q[front++];
        for (edge *e=v[now];e;e=e->next)
            if (!depth[e->e])
            {
                depth[e->e]=depth[now]+1;
                fd[e->e]=e->d;
                f[e->e][0]=now;
                int p=now,x=0;
                while (f[p][x])
                {
                    f[e->e][x+1]=f[p][x];
                    p=f[p][x];
                    x++;
                }
                q[++tail]=e->e;
            }
    }
    int cnt=0;
    for (int a=n;a>=1;a--)
    {
        int now=q[a];
        start[now]=cnt+1;
        for (edge *e=v[now];e;e=e->next)
            if (depth[e->e]==depth[now]+1)
            {
                z[++cnt]=value[e->e]+e->d;
                value[now]+=value[e->e]+e->d;
            }
        z[++cnt]=tot-value[now];
        end[now]=cnt;
        sort(z+start[now],z+end[now]+1);
        sum[end[now]][0]=z[end[now]];
        sum[end[now]][1]=0;
        for (int a=end[now]-1;a>=start[now];a--)
        {
            sum[a][0]=sum[a+1][0];
            sum[a][1]=sum[a+1][1];
            if ((a&1)==(end[now]&1)) sum[a][0]+=z[a];
            else sum[a][1]+=z[a];
        }
        cnt++;
    }
    for (int a=1;a<=m;a++)
    {
        int p1,p2;
        scanf("%d%d",&p1,&p2);
        int lca=get_lca(p1,p2);
        int dist=depth[p1]+depth[p2]-2*depth[lca];
        int delta=dist/2+(dist&1);
        int px,px1,px2;
        if (depth[p1]-depth[lca]<delta) px=get(p2,dist-delta);
        else px=get(p1,delta);
        if (depth[p1]-depth[lca]<delta-1) px1=get(p2,dist-delta+1);
        else px1=get(p1,delta-1);
        if (depth[p2]-depth[lca]<dist-delta-1) px2=get(p1,delta+1);
        else px2=get(p2,dist-delta-1);
        int ans=0;
        if (p1==px)
        {
            if (p2==px) ans=sum[start[px]][0];
            else
            {
                int v2=calc(px2,px);
                int p=calcp(px,v2);
                ans=sum[p+1][0]+sum[start[px]][1]-sum[p][1];
            }
        }
        else
        {
            if (p2==px)
            {
                int v1=calc(px1,px);
                int p=calcp(px,v1);
                ans=v1+sum[p+1][1]+sum[start[px]][0]-sum[p][0];
            }
            else
            {
                int v1=calc(px1,px);
                int pp1=calcp(px,v1);
                int v2=calc(px2,px);
                int pp2=calcp(px,v2);
                if (pp2==pp1) pp2++;
                if (pp1>pp2) swap(pp1,pp2);
                ans=v1+sum[pp2+1][dist&1]+sum[pp1+1][1-(dist&1)]-sum[pp2][1-(dist&1)]+sum[start[px]][dist&1]-sum[pp1][dist&1];
            }
        }
        printf("%d\n",ans);
    }

    return 0;
}
AC

 

 

题解:动态规划

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>

using namespace std;

#define now pre[a][b][c][d][e][s1][s2][s3][s4]
#define dis(a,b,c,d) (abs(a-c)+abs(b-d))

const int INF=0x3f3f3f3f;

int A,B,C,D,E,num[10][10],value[10][10][10],delta[10][10][40],dp[31][6][6][6][6][2][2][2][2];

char s[500];

bool map[6][6][6][6];

int main()
{
    freopen("c.in","r",stdin);
    freopen("c.out","w",stdout);

    scanf("%d%d%d%d%d",&A,&B,&C,&D,&E);
    for (int a=0;a<6;a++)
    {
        scanf("%s",s);
        int p=0;
        for (int b=0;b<6;b++)
        {
            int px=p;
            while (s[px]!=']')
                px++;
            p++;
            num[a][b]=s[p]-'0';
            p++;
            p++;
            for (int c=1;c<=num[a][b];c++)
            {
                int v=0;
                while (s[p]>='0' && s[p]<='9')
                {
                    v=v*10+s[p]-'0';
                    p++;
                }
                value[a][b][c]=v;
                p++;
            }
            p=px+1;
        }
    }
    int base=0;
    for (int a=0;a<6;a++)
        for (int b=0;b<6;b++)
            if (a>=2 && a<=3 && b>=2 && b<=3) ;
            else
            {
                sort(value[a][b]+1,value[a][b]+num[a][b]+1);
                for (int c=2;c<=num[a][b];c++)
                    if (value[a][b][c]-value[a][b][c-1]==1) base+=A;
                for (int c=2;c<=3;c++)
                    for (int d=2;d<=3;d++)
                    {
                        if (dis(a,b,c,d)==1)
                        {
                            for (int e=1;e<=num[a][b];e++)
                            {
                                delta[c][d][value[a][b][e]]+=B;
                                delta[c][d][value[a][b][e]-1]+=C;
                                delta[c][d][value[a][b][e]+1]+=C;
                            }
                        }
                        if (dis(a,b,c,d)==2)
                        {
                            for (int e=1;e<=num[a][b];e++)
                            {
                                delta[c][d][value[a][b][e]]+=D;
                                delta[c][d][value[a][b][e]-1]+=E;
                                delta[c][d][value[a][b][e]+1]+=E;
                            }
                        }
                    }
                for (int c=0;c<6;c++)
                    for (int d=0;d<6;d++)
                        if (dis(a,b,c,d)<=2 && (c!=a || d!=b) && !map[a][b][c][d])
                        {
                            map[a][b][c][d]=map[c][d][a][b]=true;
                            if (c>=2 && c<=3 && d>=2 && d<=3) ;
                            else
                            {
                                int dist=dis(a,b,c,d);
                                for (int e=1;e<=num[a][b];e++)
                                    for (int f=1;f<=num[c][d];f++)
                                    {
                                        if (abs(value[a][b][e]-value[c][d][f])==0)
                                        {
                                            if (dist==1) base+=B;
                                            else base+=D;
                                        }
                                        if (abs(value[a][b][e]-value[c][d][f])==1)
                                        {
                                            if (dist==1) base+=C;
                                            else base+=E;
                                        }
                                    }
                            }
                        }
            }
    memset(dp,0x3f,sizeof(dp));
    dp[0][0][0][0][0][0][0][0][0]=base;
    for (int a=0;a<30;a++)
        for (int b=0;b<=num[2][2];b++)
            for (int c=0;c<=num[2][3];c++)
                for (int d=0;d<=num[3][2];d++)
                    for (int e=0;e<=num[3][3];e++)
                        for (int s1=0;s1<=1;s1++)
                            for (int s2=0;s2<=1;s2++)
                                for (int s3=0;s3<=1;s3++)
                                    for (int s4=0;s4<=1;s4++)
                                        if (dp[a][b][c][d][e][s1][s2][s3][s4]!=INF)
                                        {
                                            int v=dp[a][b][c][d][e][s1][s2][s3][s4];
                                            for (int sx1=0;sx1<=(b!=num[2][2]);sx1++)
                                                for (int sx2=0;sx2<=(c!=num[2][3]);sx2++)
                                                    for (int sx3=0;sx3<=(d!=num[3][2]);sx3++)
                                                        for (int sx4=0;sx4<=(e!=num[3][3]);sx4++)
                                                        {
                                                            int wmt=0;
                                                            if (sx1) 
                                                            {
                                                                wmt+=delta[2][2][a+1];
                                                                if (s1) wmt+=A;
                                                                if (s2) wmt+=C;
                                                                if (s3) wmt+=C;
                                                                if (s4) wmt+=E;
                                                            }
                                                            if (sx2) 
                                                            {
                                                                wmt+=delta[2][3][a+1];
                                                                if (s1) wmt+=C;
                                                                if (s2) wmt+=A;
                                                                if (s3) wmt+=E;
                                                                if (s4) wmt+=C;
                                                            }
                                                            if (sx3) 
                                                            {
                                                                wmt+=delta[3][2][a+1];
                                                                if (s1) wmt+=C;
                                                                if (s2) wmt+=E;
                                                                if (s3) wmt+=A;
                                                                if (s4) wmt+=C;
                                                            }
                                                            if (sx4) 
                                                            {
                                                                wmt+=delta[3][3][a+1];
                                                                if (s1) wmt+=E;
                                                                if (s2) wmt+=C;
                                                                if (s3) wmt+=C;
                                                                if (s4) wmt+=A;
                                                            }
                                                            if (sx1 && sx2) wmt+=B;
                                                            if (sx1 && sx3) wmt+=B;
                                                            if (sx1 && sx4) wmt+=D;
                                                            if (sx2 && sx3) wmt+=D;
                                                            if (sx2 && sx4) wmt+=B;
                                                            if (sx3 && sx4) wmt+=B;
                                                            int &t=dp[a+1][b+sx1][c+sx2][d+sx3][e+sx4][sx1][sx2][sx3][sx4];
                                                            if (t>v+wmt) t=v+wmt;
                                                        }
                                        }
    int ans=INF;
    for (int a=0;a<=1;a++)
        for (int b=0;b<=1;b++)
            for (int c=0;c<=1;c++)
                for (int d=0;d<=1;d++)
                    ans=min(ans,dp[30][num[2][2]][num[2][3]][num[3][2]][num[3][3]][a][b][c][d]);
    printf("%d\n",ans);

    return 0;
}
AC

ql

转载于:https://www.cnblogs.com/zzyh/p/7620074.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值