zoukankan      html  css  js  c++  java
  • 纪念第一次ak。。。

    1.MM的数学作业

    【题目大意】

    今天,MM在上数学课,数学课的主题是函数。讲完以后老师留了一个家庭作业,让同学们回家思考。题目如下:

    定义一个函数,F(x)表示x转成二进制后,二进制中“1”的个数。比如F(279)=5,因为(279)10=( 100010111)2,其中有5个“1”。

    现在有一个序列,已知X0 = 0,Xi=F(Xi-1)*A+B。老师的问题是求这个序列第K个是多少。

    【输入格式】

    输入3个整数,A,B,K,定义如上所述。

    【输出格式】

    输出只有一行,序列的第K个的值。

    【样例输入】

    1

    7

    2

    【样例输出】

    10

    【数据范围】

    0<=A,B<= 1,000,000

    30% 数据1<=K<=1,000,000

    100% 数据1<=K<=1,000,000,000

    题解:

    考虑到f函数的值非常少,而且这个数的大小只和f有关,所以

    可以记录一下循环节,节约时间

    代码:

    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    int a[30000005],A,B,n;
    int f(int x)
    {
        int num=0;
        while (x)
         {
             if (x%2)num++;
             x/=2;
         }
        return num; 
    }
    int main()
    {
        freopen("homework.in","r",stdin);
        freopen("homework.out","w",stdout);
        scanf("%d%d%d",&A,&B,&n);
        int now=0;
        for (int i=1;i<=n;i++)
         {
             now=f(now)*A+B;
             if (a[now])
              {
                  int p=now; 
                  for (int j=1;j<=(n-i)%(i-a[now]);j++)p=f(p)*A+B;
                  printf("%d
    ",p);
                  return 0;
              }
             a[now]=i; 
         }
        printf("%d
    ",now); 
    }

    2.香蕉树

    【题目大意】

        MM家的后院种了一棵香蕉树,由于树上的香蕉过多,导致整棵树不漂亮了,所以她需要通过摘香蕉来修整这棵树。但是,如果她摘了过多的香蕉就会使,整棵树太稀疏,不够饱满,所以她最多只能摘M个香蕉。香蕉是长在树枝上的,切每条树枝上至少保留Ci个。MM希望摘完香蕉后,使得根到最沉的叶子最轻。轻重的衡量就是,根到某个叶子路径上还剩下的香蕉总数。树根为1号点。

    【输入格式】

    第一行两个整数N,M,表示树的节点个数,她最多能摘的香蕉个数。

    接下来N-1行,每行四个整数Xi,Yi,Pi,Ci,表示第i个树枝连接的两个端点 ,以及这条树枝上的香蕉总数和至少应该保留的香蕉数。

    【输出格式】

    输出只有一行,表示根到最沉的叶子最轻是多少。

    【样例输入】

    3 200

    1 2 200 100

    2 3 450 250

    【样例输出】

    450

    【数据范围】

     1<=N<=100000

     0<=M<=1000000

     0<=Pi,Ci<=10000

    题解:

    二分答案,贪心。

    首先肯定是能往上就往上

    而且叶子节点最后的重量肯定是最大的

    那么将叶子节点的重量排序,然后看看它的祖先是不是被之前覆盖过

    覆盖过就可以节约了

    代码:

    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N=200005;
    int n,m,x,y,u,v,ne[N],fi[N],zz[N],sl[N],ql[N],can[N],zhong[N];
    int fa[N],num,ye[N],flag[N],f[N][21];
    void jb(int x,int y,int u,int v)
    {
        ne[++num]=fi[x];
        fi[x]=num;
        zz[num]=y;
        sl[num]=u;
        ql[num]=v;
    }
    void dfs(int x,int y,int z,int s)
    {
        fa[x]=y; 
        zhong[x]=z;
        can[x]=s;
        for (int i=fi[x];i;i=ne[i])
         if (y!=zz[i])dfs(zz[i],x,z+sl[i],s+ql[i]);
        if (!ne[fi[x]]&&zz[fi[x]]==y)ye[++num]=x; 
    }
    int find(int x)
    {
        for (int j=19;j>=0;j--)
         if (!flag[f[x][j]])x=f[x][j];
        if (!flag[x])x=f[x][0]; 
        return x; 
    }
    bool cmp(int x,int y)
    {
        return zhong[x]>zhong[y];
    }
    int pd(int x)
    {
        int p=0;
        memset(flag,0,sizeof flag);
        flag[0]=flag[1]=1;
        for (int i=1;i<=num;i++)
         {
             if (zhong[ye[i]]<=x)return 1;
             if (zhong[ye[i]]-can[ye[i]]>x)return 0;
             int l=find(ye[i]);
             if (can[l]<zhong[ye[i]]-x)p=p-can[l]+zhong[ye[i]]-x;
             if (p>m)return 0;
             l=ye[i];
             while (l!=1)
              {
                  if (flag[l])break;
                  flag[l]=1;
                  l=fa[l];
              }
         }
        return 1;
    }
    int main()
    {
        freopen("banana.in","r",stdin);
        freopen("banana.out","w",stdout);
        scanf("%d%d",&n,&m);
        for (int i=1;i<n;i++)
         {
             scanf("%d%d%d%d",&x,&y,&u,&v);
             jb(x,y,u,u-v);
             jb(y,x,u,u-v);
         }
        num=0; 
        dfs(1,0,0,0);
        sort(ye+1,ye+num+1,cmp);
        for (int i=1;i<=n;i++)f[i][0]=fa[i];
        for (int i=1;i<20;i++)
         for (int j=1;j<=n;j++)
          f[j][i]=f[f[j][i-1]][i-1];
        int l=0,r=1e9;
        while (l<r)
         {
            int mid=(l+r)/2;
            if (!pd(mid))l=mid+1;
            else r=mid;
         } 
        printf("%d",l); 
    } 

    3.迷路

    【问题描述】

    Amber在有向图中迷路了。

    该有向图有 个节点,Amber从节点 出发,他必须恰好在 时刻到达节点 N-1

    现在给出该有向图,你能告诉Amber总共有多少种不同的路径吗?

    注意:Amber不能在某个节点逗留,且通过某有向边的时间严格为给定的时间。

    【输入格式】

    输入文件road.in第一行包含两个整数,N T

    接下来有 行,每行一个长度为 的字符串。

    i行第j列为'0'表示从节点i到节点j没有边。

    '1''9'表示从节点i到节点j需要耗费的时间。

    【输出格式】

    输出文件road.out包含一个整数,可能的路径数,这个数可能很大,只需输出这个数除以2009的余数。

    【输入样例一】

    2 2

    11

    00

    【输出样例一】

    1

    【样例解释一】

    0->0->1

    【输入样例二】

    5 30

    12045

    07105

    47805

    12024

    12345

    【输出样例二】

    852

    【数据规模和约定】

    30%的数据,满足 2 <= N <= 5 ; 1 <= T <= 30 

    100%的数据,满足 2 <= N <= 10 ; 1 <= T <= 1000000000 

    题解:

    看到那么大的T,一看就是矩阵

    构造(9*n)*(9*n)的矩阵

    快速幂T次

    矩阵构造看代码。。。

    代码:

    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N=12;
    const int M=2009;
    char s[N];
    int T,a[N][N],n;
    struct zz
    {
        int a[N*N][N*N];
    }x;
    zz cf(zz x,zz y)
    {
        zz z;
        memset(z.a,0,sizeof z.a);
        for (int i=1;i<=9*n;i++)
         for (int j=1;j<=9*n;j++)
          for (int k=1;k<=9*n;k++)
           (z.a[i][j]+=(x.a[i][k]*y.a[k][j]))%=M;
        return z;   
    }
    void gouzao()
    {
        for (int i=1;i<=n;i++)
         for (int j=1;j<=n;j++)
          if (a[i][j]!=-1)x.a[i][(a[i][j]-1)*n+j]=1;
        for (int i=n+1;i<=9*n;i++)
         x.a[i][i-n]=1;
    }
    void ksm(int k)
    {
        zz y;
        memset(y.a,0,sizeof y.a);
        for (int i=1;i<=9*n;i++)y.a[i][i]=1;
        for (;k;k/=2,x=cf(x,x))
         if (k%2)y=cf(y,x);
        x=y;  
    }
    int main()
    {
        freopen("road.in","r",stdin);
        freopen("road.out","w",stdout); 
        scanf("%d%d",&n,&T);
        for (int i=1;i<=n;i++)
         {
             scanf("%s",s+1);
            for (int j=1;j<=n;j++)
             if (s[j]!='0')
              a[i][j]=s[j]-48;
              else a[i][j]=-1; 
         }
        gouzao();
        ksm(T);
        printf("%d",x.a[1][n]); 
    } 
  • 相关阅读:
    ArduinoYun教程之ArduinoYun硬件介绍
    Nmap扫描教程之基础扫描详解
    Nmap扫描教程之Nmap基础知识
    Nmap扫描教程之DNS服务类
    Nmap扫描教程之网络基础服务DHCP服务类
    Xamarin iOS教程之自定义视图
    Xamarin iOS教程之警告视图
    Xamarin iOS教程之页面控件
    使用光学鼠标传感器实现旋转(或线性)测量(转)
    基于STM32的uCOS-II移植详解
  • 原文地址:https://www.cnblogs.com/xuanyiming/p/7544704.html
Copyright © 2011-2022 走看看