• JNU周练1013


    CodeForces 337A

     给出n、m(n<=m)和m个数字,在m个数字中选n个数字,令这n个数字中最大数与最小数值差最小。

    数据量小,直接暴力

    #include <iostream>
    #include <algorithm>
    using namespace std;

    int main()
    {
        int a[60], n, m;
        cin >> n >> m;
        for(int i = 0; i < m; i++)
            cin >> a[i];
        sort(a, a+m);
        int min = 1005;
        for(int i=0; i<=m-n; i++)
        {
            if(a[i+n-1] - a[i] < min)
                min = a[i+n-1] - a[i];
        }
        cout << min << endl;
        return 0;
    }
    View Code 

    CodeForces 337B

    给出屏幕与电影的宽高比,电影按比例缩放,尽量占满屏幕,求屏幕没被占的面积的比例。输出要求:分子分母互质。

    找规律,无论是电影适应屏幕还是屏幕适应电影,得出的比例都是一样的。同时注意两比例相同时输出0/1。

    #include <iostream>
    using namespace std;

    int gcd(int x, int y)
    {
        int r;
        while(y!=0)
        {
            r = x%y;
            x = y;
            y = r;
        }
        return x;
    }

    int main()
    {
        int a, b, c, d, temp;
        cin >> a >> b >> c >> d;
        a = a * d;
        c = c * b;
        if(a < c)  
        {
            temp = a;
            a = c;
            c = temp;
        }
        c = a - c;
        temp = gcd(a,c);
        a /= temp;
        c /= temp;
        cout << c << "/" << a << endl;
        return 0;
    }
    View Code 


    CodeForces 337C

    /*
        题意:
        一人去参加比赛。每答对一题得一分。连续答对k题时先加一分然后总分数乘2然后连续答对题数归0。
        然后给你题目总数n和他答对题目的个数m问你他能得的最低分是多少。

        要获得最低分,要尽量避免连续答对k题,或者让连续答对k题的情况尽量出现在分数少的时候
        方法是:设答对为1,答错为0,以k-1个"1"和1个"0"为一组从后往前排列,
        最后得出两部分,一部分是x组k-1个"1"和1个"0",另一部分为连续y个1
        则n = k * x + y;  m = (k-1) * x + y;  ---> 得 x = n - m

        第一部分好求:(k-1) * x
        第二部分需要找规律:
        另z = y / k,则有z*k次答对,取z = 1, 2, 3,...总分数如下
        那么分数变化为:2*k,(2*k+k)*2,((2*k+k)*2+k)*2......。
        抽象出来这就是一个数列递推公式为:a[z]=2*(a[z-1]+k)。
        展开移项后得:a[z]+2*k=2*(a[z-1]+2*k)。设c[z]=a[z]+2*k。那么c[z]/c[z-1]=2。等比数列。
        而c[0]=a[0]+2*k=2k。那么c[z]=2*k*2^z。所以a[z]=k*2^(z+1)-2*k。

        数据大,要用到快速幂


    */

     注意中间数大,要开long long

    #include <iostream>
    using namespace std;

    const long long MOD = 1000000009;

    //计算a^bmodn     
    long long modexp_recursion(long long a,long long b,long long n)     
    {    
        long long t = 1;

        if (b == 0)
            return 1;

        if (b == 1)
             return a%n;

        t = modexp_recursion(a, b>>1, n);

        t = t*t % n;

        if (b&0x1)
        {    
            t = t*a % n;
        }

        return t;
     } 

    int main()
    {
        long long n, m, k;
        cin >> n >> m >> k;
        long long a = m / (k-1);
        if(a <= n - m)
            cout << m << endl;
        else
        {
            long long ret = 0;
            a = n - (n-m)*k;
            long long b = a / k;
            if(b>0)
            {
                //cout << "b:" << b << endl;
                
    //cout << modexp_recursion(2, b, MOD) << endl;
                ret = 2 * k * modexp_recursion(2, b, MOD) - 2*k;
                ret = ret % MOD;
                //cout << "ret:" << ret << endl;
            }
            ret = (ret + (n-m) * (k-1)) % MOD;
            ret = (ret + (a-a/k*k)) % MOD;
            cout << ret << endl;
            //cout << "aaa:" << modexp_recursion(2,100,MOD) << endl;
        }
        return 0;
    }
    View Code 
    CodeForces 337D

    题意:给一棵n个结点的树,任意两个节点的距离是指连接两点的最短的边数

    在树上的某个结点有一个“恶魔之书”,这本书会让距离它d以内的节点都受到影响

    已知有m个节点收到了影响,问最多有几个结点可能放着“恶魔之书”?

    据说是树形dp,看题解知道大概思路后,自己写代码,挑了无数bug过了。。

    规定点1为根节点 

    dp[i][0] --- 代表节点 i 子树中距 i 最远的受影响点和 i 的距离。

    dp[i][1] --- 上述的次远距离

    dp[i][2] --- 代表节点 i 子树以外的部分 距 i 最远的受影响点和 i 的距离。

    若某点dp[i][0] 和 dp[i][2]均小于或等于影响范围d,表示该点满足条件。

     dp[i][0] 和 dp[i][1]好求,dp[i][2] 则要综合(1) i 的祖先节点和(2)其父节点的其他子树的情况。

    状态转移方程: 

    u(父)--- v(子)

    fa(父) --- u, i (子)

    dp[u][0] = max(dp[v][0] + 1)

    dp[u][2] =  max(dp[fa][2], {dp[fa][0] or dp[fa][1]} + 1)   

    #include <iostream>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    #define N 100010
    #define M 200010

    int head[N], vid[N], vis[N], eNum, n, m, d;
    struct Edge
    {
        int e;
        int next;
    }edge[M];

    int dp[N][3];

    void AddEdge(int u, int v)
    {
        edge[eNum].e = v;
        edge[eNum].next = head[u];
        head[u] = eNum++;
    }

    void init()
    {
        int temp, u, v;
        eNum = 0;
        memset(head, -1sizeof(head));
        memset(vis, 0sizeof(vis));
        memset(dp, -1sizeof(dp));
        cin >> n >> m >> d;
        for(int i=1; i<=m; i++)
        {
            cin >> temp;
            vis[temp] = 1;
        }
        for(int i=1; i<n; i++)
        {
            cin >> u >> v;
            AddEdge(u, v);
            AddEdge(v, u);
        }
    }

    void dfs1(int u, int fa)
    {
        if(vis[u]==1) dp[u][0] = 0;
        for(int i = head[u]; i != -1; i = edge[i].next)
        {
            int v = edge[i].e;
            if(v == fa) continue;
            dfs1(v, u);
            if(dp[v][0] + 1 > dp[u][0])
            {
                if(dp[v][0]!=-1)
                {
                    dp[u][1] = dp[u][0];
                    dp[u][0] = dp[v][0] + 1;
                }
            }
            else if(dp[v][0] + 1 > dp[u][1] && dp[v][0] != -1)
            {
                dp[u][1] = dp[v][0] + 1;
            }

        }
    }

    void dfs2(int u, int fa)
    {
        if(vis[u]==1 && dp[u][2]==-1) dp[u][2] = 0;
        for(int i=head[u]; i != -1; i = edge[i].next)
        {
            int v = edge[i].e;
            if(v == fa) continue;
            if(dp[u][2]!=-1) dp[v][2] = dp[u][2] + 1;
            if(dp[v][0]+1 == dp[u][0])
            {
                if(dp[u][1] != -1)
                    dp[v][2] = max(dp[v][2], dp[u][1]+1);
            }
            else if(dp[u][0]!=-1)
                dp[v][2] = max(dp[v][2], dp[u][0]+1);
            dfs2(v, u);
        }
    }

    int main()
    {
        init();
        dfs1(10);
        dfs2(10);
        int ans = 0;
        for(int i=1; i<=n; i++)
            if(dp[i][0]<=d && dp[i][2]<=d)
                ans++;
        //for(int i=1; i<=n; i++)
        
    //{
        
    //    cout << dp[i][0] << "   " << dp[i][1] << "   " << dp[i][2] << endl;
        
    //}
        cout << ans << endl;
        return 0;
    }
    /*
    9 4 3
    1 2 8 9
    1 5
    5 4
    4 3
    3 2
    5 6
    6 7
    7 8
    8 9

    */
    View Code 

     CodeForces 337E

     题意,给你一颗n个数,构建一颗树,包含所有数,满足根结点等于儿子结点的乘积,并且所有叶子结点都是素数。

    关键点:对每个a[i]分解质因子,得出因子个数。在此基础上建树,由于n<=8,所以直接dfs枚举所有情况,得出最小的结点数。 

    #include <iostream>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    struct Num
    {
        long long b;
        int c;
    }num[10];
    int n; //存输入
    int a[80000], index;
    long long leftt[10];//标记剩余多少
    int vis[10], sum, ans_min;

    int prime(int x)
    {
        int flag = 0;
        for(int i=2; i*i<=x; i++)
        {
            if(x%i==0)
            {
                flag = 1;
                break;
            }
        }
        if(flag)
            return 0;
        return 1;
    }

    //筛选法求1000000内素数
    int prime1(int x)
    {
        int flag = 0;
        for(int i=0; a[i]*a[i]<=x; i++)
        {
            if(x%a[i]==0)
            {
                flag = 1;
                break;
            }
        }
        if(flag)
            return 0;
        return 1;
    }

    bool cmp(Num a, Num b)
    {
        return a.c < b.c;
    }

    void dfs(int t)
    {
        //cout << "t: " << t << endl;
        if(t == n)
        {
            int ret = sum, retn = n;
            for(int i=1; i<=n; i++)
            {
                if(vis[i]!=0)
                {
                    ret -= num[i].c;
                    retn --;
                }
            }
            if(retn>1) ret++;
            if(ret < ans_min) ans_min = ret;
            //------test
            
    //if(ret==8)
            
    //{
            
    //    for(int i=1; i<=n; i++)
            
    //    {
            
    //        cout << vis[i]<<endl;
            
    //    }
            
    //}
            return ;
        }

        for(int i=t+1; i<=n; i++)
        {
            long long temp = leftt[i];
            if(leftt[i] >= num[t].b && leftt[i]%num[t].b==0)
            {
                leftt[i] /= num[t].b;
                vis[t] = i;
            }
            dfs(t+1);
            if(temp!=leftt[i])
            {
                leftt[i] *= num[t].b;
                vis[t] = 0;
            }
        }
    }

    int main()
    {
        long long flag;
        index = 0;
        for(int i=2; i<=1000; i++)
        {
            if(prime(i))
                a[index++] = i;
        }
        for(int i=1001; i<=1000000; i++)
        {
            if(prime1(i))
                a[index++] = i;
        }

        cin >> n;
        for(int i=1; i<=n; i++)
            cin >> num[i].b;
        for(int i=1; i<=n; i++)
        {
            num[i].c = 0; flag = num[i].b;
            for(int j=0; j<index && flag>1; )
            {
                if(flag%a[j]==0)
                {
                    flag /= a[j];
                    num[i].c ++;
                }
                else
                {
                    j++;
                }
            }
            //原数<=10^12,除遍10^6内的素数后,若该数仍大于0,则一定有且仅一个10^6+1~10^12的质因子
            if(flag>1) num[i].c++;
        }
        sort(num+1, num+n+1, cmp);

        sum = 0, ans_min = 1000000000;
        memset(vis,0,sizeof(vis));
        for(int i=1; i<=n; i++)
        {
            leftt[i] = num[i].b;
            sum += num[i].c;
            if(num[i].c!=1) sum++;
        }
        //cout << "sum: " << sum << endl;
        dfs(1);
        cout << ans_min << endl;

        //for(int i=1; i<=n; i++)
        
    //    cout << num[i].b << ": " << num[i].c << endl;
        
    //cout << index << endl;
        
    //cout << a[index-1] << endl;
        return 0;
    }
    View Code 
  • 相关阅读:
    Android安全-代码安全1-ProGuard混淆处理
    快速提高Android开发效率的Web工具
    Android采用ListView实现数据列表显示2-使用SimpleAdapter进行数据绑定
    Java中Enum方法toString与ordinal方法
    视一:Web前端开发之HTML+CSS
    100-days: thirty-seven
    css 权重
    100-days: thirty-six
    100-days: thirty-five
    100-days: thirty-four
  • 原文地址:https://www.cnblogs.com/byluoluo/p/3369584.html
Copyright © 2020-2023  润新知