ACM ICPC 2017 Warmup Contest 1(Nordic Collegiate Programming Contest 2016)

国庆训练开始
由于部分原因,在家和队友做了训练,第一场,由于新疆icpc因19大推迟,使我们又多了大量时间,那么就开始吧。
其实这场感觉还不错,单人作战组队赛,4题,险些5题收场,还可以吧


首先看了前四题,发现并不是很可以做,于是,突然发现签到题在倒数第二题,赶快a了,跟一波步伐


J. Jumbled Compass

思路:纯粹的签到题,指针转法,顺时针逆时针比较一下大小就好了,注意一下度数取模,ac

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;

const int maxn = 1e5+10;

int myabs(int k)
{
    if(k>0)
    {
        return k;
    }
    else
    {
        return (-1) * k;
    }
}

int main()
{
    int n1,n2;
    while(scanf("%d%d",&n1,&n2)!=EOF)
    {
        int a = n2-n1;
        if(a<0)
        {
            a += 360;
        }
        int b = myabs(360-a);
        if(a<=b)
        {
            printf("%d\n",a);
        }
        else
        {
            printf("%d\n",(-1)*b);
        }
    }
    return 0;
}

G. Game Rank

思路:典型的细节模拟题,读清题,把题中每一个细节都考虑到就可以了
1.胜升败降
2.超分升级,负分降级
3.传奇不降
4.一星不降
5.六阶下三连胜加成
最后注意条件4零分时特判一下,并且传奇单独输出就好了

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;

const int maxn = 1e4+10;

char game[maxn];
int upgrade[26] = {0,5,5,5,5,5,5,5,5,5,5,4,4,4,4,4,3,3,3,3,3,2,2,2,2,2};

int main()
{
    while(scanf("%s",game)!=EOF)
    {
        int len = strlen(game);
        int star = 0;
        int myrank = 25;
        int conwin = 0;
        for(int i=0;i=6&&conwin>=3)
                {
                    star++;
                }
                if(myrank>0&&star>upgrade[myrank])
                {
                    star -= upgrade[myrank];
                    myrank--;
                }
            }
            else
            {
                conwin = 0;
                if(myrank>0&&myrank<=20)
                {
                    star--;
                    if(myrank==20&&star<0)
                    {
                        star++;
                    }
                }
                if(star<0)
                {
                    myrank++;
                    star += upgrade[myrank];
                }
            }
        }
        if(myrank==0)
        {
            printf("Legend\n");
        }
        else
        {
            printf("%d\n",myrank);
        }
    }
    return 0;
}



E. Exponial

思路:阶乘级幂指数运算,看了一眼直接飙飞的大数,毫无以为降幂公式咯
降幂公式,肯定不能是三角降幂,想到费马小定理降幂A^x%p=A^(x%(p-1))%p
这里要求p是素数,成立,然而,这里的模数显然过大了,还是不可做
于是想到欧拉降幂A^x%p=A^(x%ψ(p)+ψ(p))%p,这里ψ(p)为p的欧拉函数,这里欧拉函数就比较小了,完全是个可行的方案
这里的条件为x>ψ(p),那么分类讨论一下就好了,按样例中的5作为分界
然后最后一个问题,这里的n高达1e9,如果直接循环的话肯定会tle,然而其实可以发现一个小诀窍
exponial(n) %p= n^(exponial(n-1))%p;
再用欧拉降幂
exponial(n) %p=n^(exponial(n-1))%p=n^(exponial(n-1)%ψ(p)+ψ(p))%p
exponial(n) %p=F(exponial(n-1)%ψ(p))
F函数可以用快速幂算
于是,便可以递归了,偶然间发现,当模数即ψ(p)=1时,exponial(n-1)%ψ(p)=0,由于欧拉函数下降速度还是比较快的,于是这个大剪枝就完全可以将O(1e9)的复杂度降下了了,成功ac

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;

const int maxn = 1e6+10;

int euler(int n)
{
    int cnt = n;
    for(int i=2; i * i <= n; i++)
    {
        if(n % i == 0)
        {
            cnt -= cnt / i;      //   m-m/p
            while(n % i == 0)
            {
                n /= i;
            }
        }
    }
     if(n > 1)
     {
         cnt -= cnt / n;
     }
    return cnt;
}


long long Power(long long a0,long long k,long long mode)
{
	long long b0 = 1;
	while(k)//k>0
	{
		if(k&1)//k % 2 == 1
		{
			b0 = b0 * a0 % mode;
		}
		a0 = a0 * a0 % mode;
		k >>= 1; //k/=2;
	}
	return b0;
}
long long exponial(long long n,long long m)
{
    if(m==1)
    {
        return 0;
    }
    if(n<=5)
    {
        long long now = 1;
        for(int i=1;i<=n;i++)
        {
            now = Power(i,now,m);
        }
        return now;
    }
    else
    {
        //n %= m;
        long long eulerc = euler(m);
        long long mm = exponial(n-1,eulerc);
        return Power(n,mm+eulerc,m);
    }
}

int main()
{
    long long n,m;
    while(scanf("%lld%lld",&n,&m)!=EOF)
    {
        printf("%lld\n",exponial(n,m));
    }
    return 0;
}


 D. Daydreaming Stockbroker

思路:最后一题,又是个水题,本来以为会是个dp,后来发现并没有这么复杂,低价买,高价卖,模拟一遍就ok了

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;

const int maxn = 1e5+5;

long long p[maxn];

int main()
{
    int d;
    while(scanf("%d",&d)!=EOF)
    {
        for(int i=1;i<=d;i++)
        {
            scanf("%lld",&p[i]);
        }
        long long sum = 100;
        long long num = 0;
        bool increase = false;
        for(int i=2;i<=d;i++)
        {
            if(increase)
            {
                if(p[i]p[i-1])
                {
                    long long tb = sum / p[i-1];
                    if(tb > 1e5)
                    {
                        tb = 1e5;
                    }
                    sum -= p[i-1] * tb;
                    num += tb;
                    increase = true;
                }
            }
        }
        sum += num * p[d];
        printf("%lld\n",sum);
    }
    return 0;
}




 F. Fleecing the Raffle

思路:这题是后来补的,一开始队友做崩了,以为要高精度什么的,后来发现其实并不需要这么麻烦
就是一个排列组合公式C(1,k)*C(p-1,n)/C(p,n+k)
对于k,一开始想写个三分,后来找规律可以发现k=n / (p-1),向下取整
化简发现,分子分母刚好都有k项
分子为p*k*π(n-p+i),i=2~k
分母为(n+1)*π(n+i),i=2~k
于是写个循环,成功


#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;

const int maxn = 1e5+10;

/*typedef long long LL;

LL Power_mod(LL a, LL b, LL p)
{
    LL res = 1;
    while(b!=0)
    {
        if(b&1) res = (res*a)%p;
        a = (a*a)%p;
        b >>= 1;
    }
    return res;
}
LL Comb(LL a,LL b, LL p)
{
    if(a < b) return 0;
    if(a == b) return 1;
    if(b > a-b) b = a-b;
    LL ans = 1, ca = 1, cb = 1;
    for(LL i=0; i

文章地址:http://blog.csdn.net/owen_q/article/details/78177706

你可能感兴趣的:(模拟,水题,数学,快速幂,贪心,递推,计蒜客,数论,找规律,排列组合)