zoukankan      html  css  js  c++  java
  • noip2013day1解题报告

    1.转圈游戏

    题目描述

    n 个小伙伴(编号从 0 到 n-1)围坐一圈玩游戏。按照顺时针方向给 n 个位置编号,从0 到 n-1。最初,第 0 号小伙伴在第 0 号位置,第 1 号小伙伴在第 1 号位置,……,依此类推。游戏规则如下:每一轮第 0 号位置上的小伙伴顺时针走到第 m 号位置,第 1 号位置小伙伴走到第 m+1 号位置,……,依此类推,第n − m号位置上的小伙伴走到第 0 号位置,第n-m+1 号位置上的小伙伴走到第 1 号位置,……,第 n-1 号位置上的小伙伴顺时针走到第m-1 号位置。

    现在,一共进行了 10^k轮,请问 x 号小伙伴最后走到了第几号位置。

    输入输出格式

    输入格式:

    输入文件名为 circle.in。

    输入共 1 行,包含 4 个整数 n、m、k、x,每两个整数之间用一个空格隔开。

    输出格式:

    输出文件名为 circle.out。

    输出共 1 行,包含 1 个整数,表示 10

    k 轮后 x 号小伙伴所在的位置编号。

    输入输出样例

    输入样例#1:
    10 3 4 5
    
    输出样例#1: 
    5
    

    说明

    对于 30%的数据,0 < k < 7;

    对于 80%的数据,0 < k < 10^7;

    对于 100%的数据,1 <n < 1,000,000,0 < m < n,1 ≤ x ≤ n,0 < k < 10^9

    题解:直接用快速幂求一下,注意取膜就行。

    代码:

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    template<class T>inline void read(T &x)
    {
        x=0;int f=0;char ch=getchar();
        while(ch<'0'||ch>'9')f|=(ch=='-'),ch=getchar();
        while(ch<='9'&&ch>='0')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
        x=f?-x:x;
        return;
    }
    long long ksm(long long x,long long y,long long p)
    {
        long long r=1,base=x;
        while(y)
        {
            if(y&1)r=r*base%p;
            base=base*base%p;
            y>>=1;
        }
        return r;
    }
    int main()
    {
        long long n,m,k,x;
        read(n);read(m);read(k);read(x);
        printf("%lld
    ",(x+m*ksm(10,k,n))%n);
        return 0;
    }
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    template<class T>inline void read(T &x)
    {
        x=0;int f=0;char ch=getchar();
        while(ch<'0'||ch>'9')f|=(ch=='-'),ch=getchar();
        while(ch<='9'&&ch>='0')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
        x=f?-x:x;
        return;
    }
    long long ksm(long long x,long long y,long long p)
    {
        long long r=1,base=x;
        while(y)
        {
            if(y&1)r=r*base%p;
            base=base*base%p;
            y>>=1;
        }
        return r;
    }
    int main()
    {
        long long n,m,k,x;
        read(n);read(m);read(k);read(x);
        printf("%lld
    ",(x+m*ksm(10,k,n))%n);
        return 0;
    }

    2.火柴排队

    题目描述

    涵涵有两盒火柴,每盒装有 n 根火柴,每根火柴都有一个高度。 现在将每盒中的火柴各自排成一列, 同一列火柴的高度互不相同, 两列火柴之间的距离定义为: ∑(ai-bi)^2

    其中 ai 表示第一列火柴中第 i 个火柴的高度,bi 表示第二列火柴中第 i 个火柴的高度。

    每列火柴中相邻两根火柴的位置都可以交换,请你通过交换使得两列火柴之间的距离最小。请问得到这个最小的距离,最少需要交换多少次?如果这个数字太大,请输出这个最小交换次数对 99,999,997 取模的结果。

    输入输出格式

    输入格式:

    输入文件为 match.in。

    共三行,第一行包含一个整数 n,表示每盒中火柴的数目。

    第二行有 n 个整数,每两个整数之间用一个空格隔开,表示第一列火柴的高度。

    第三行有 n 个整数,每两个整数之间用一个空格隔开,表示第二列火柴的高度。

    输出格式:

    输出文件为 match.out。

    输出共一行,包含一个整数,表示最少交换次数对 99,999,997 取模的结果。

    输入输出样例

    输入样例#1: 
    4
    2 3 1 4
    3 2 1 4
    
    输出样例#1:
    1
    输入样例#2:
    4
    1 3 4 2
    1 7 2 4
    输出样例#2:
    2

    说明

    【输入输出样例说明1】

    最小距离是 0,最少需要交换 1 次,比如:交换第 1 列的前 2 根火柴或者交换第 2 列的前 2 根火柴。

    【输入输出样例说明2】

    最小距离是 10,最少需要交换 2 次,比如:交换第 1 列的中间 2 根火柴的位置,再交换第 2 列中后 2 根火柴的位置。

    【数据范围】

    对于 10%的数据, 1 ≤ n ≤ 10;

    对于 30%的数据,1 ≤ n ≤ 100;

    对于 60%的数据,1 ≤ n ≤ 1,000;

    对于 100%的数据,1 ≤ n ≤ 100,000,0 ≤火柴高度≤ maxlongint

    题解:注意到∑(ai-bi)^2=∑(ai^2-2ai*bi+bi^2),由排序不等式得,当第一行的每个火柴棒都与和他排名相同的排在一列时,距离最小。对于火柴棒的移动,可以只动第一行,也可以只动第二行。知道了最小距离,怎么算交换次数呢?我们将第二行的每个数要交换到的位置放进一个数组里,我们每一次交换都会使该数组的逆序对减一,所以我们求这个数组的逆序对即可。逆序对可以用归并或树状数组或线段树。因为一开始已经离散化了,所以这里用的树状数组,当数组里的数较小时,推荐用这个,因为它既好写又好调,还快。

    代码:

    #include<cstdio>
    #include<algorithm>
    const int lxn=99999997;
    using namespace std;
    template<class T>inline void read(T &x)
    {
        x=0;int f=0;char ch=getchar();
        while(ch<'0'||ch>'9')f|=(ch=='-'),ch=getchar();
        while(ch<='9'&&ch>='0')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
        x=f?-x:x;
        return;
    }
    struct node
    {
        int r,v;
        inline bool operator<(const node&A)const{
        return A.v>v;
        }
    }a[100010],b[100010];
    int Rank[100010],s[100010],n,ans;
    int lowbit(int x){return x&(-x);}
    int sum(int k)
    {
        int ans=0;
        while(k>0)
        {
            ans+=s[k];
            k-=lowbit(k);
        }
        return ans;
    }
    void add(int k)
    {
        while(k<=n)
        {
            s[k]++;
            k+=lowbit(k);
        }
    }
    int main()
    {
        read(n);
        for(int i=1;i<=n;i++)
        {
            read(a[i].v);
            a[i].r=i;
        }
        sort(a+1,a+1+n);
        for(int i=1;i<=n;i++)
        {
            read(b[i].v);
            b[i].r=i;
        }
        sort(b+1,b+1+n);
        for(int i=1;i<=n;i++)
        Rank[b[i].r]=a[i].r;
        for(int i=1;i<=n;i++)
        {
            ans=(ans+sum(n)-sum(Rank[i]-1))%lxn;
            add(Rank[i]);
        }
        printf("%d
    ",ans);
        return 0;
    }

    第三题在这里:http://www.cnblogs.com/jiangtao0508/p/7725640.html

  • 相关阅读:
    HDOJ 1846 Brave Game
    并查集模板
    HDU 2102 A计划
    POJ 1426 Find The Multiple
    POJ 3278 Catch That Cow
    POJ 1321 棋盘问题
    CF 999 C.Alphabetic Removals
    CF 999 B. Reversing Encryption
    string的基础用法
    51nod 1267 4个数和为0
  • 原文地址:https://www.cnblogs.com/jiangtao0508/p/7737855.html
Copyright © 2011-2022 走看看