[2017.9.16]队内胡策 Day 1

来源:互联网 发布:淘宝双11怎么抢购 编辑:程序博客网 时间:2024/05/22 13:26

T1:

Problem 1 赛小城玩骰子

题目描述

众所周知,a和赛小城关系很好,赛小城经常与a交(gao)流(shi),今天一早,赛小城突发奇想,要和a玩骰子。
赛小城有一个骰子,如图1所示:
图1
数字1在上方,数字2在South(南)方位,数字3在East(东)方位,每一对相反方位的数字之和是7,按照上述.数字5在North(北)方位,数字4在west(西)方位,数字6在下方,如图l所示.数字4,5,6在图1中是看不到的。
骰子的初始位置如图1所示.按照下列 6条规则旋转骰子,规则如图2和图3所示:
图2
图2中所示的4条旋转规则是将骰子按照规则指定的方位旋转90度。图3中所示的2条旋转规则是将骰子沿水平方向分别向left(左)或Right(右)方位旋转90度
图3
图3.旋转规则Left(左)、Right(右)

a想知道,从图1所示的方位开始,根据给定的一系列规别连续的旋转骰子.在该过程中位于上方的数字之和(其中包括图1所示的初始方位上的数字1),赛小城被a的问题难住了,于是他向学习OI的你求助,你能帮帮他吗?

输入描述
第一行输入一个整数n,表示执行旋转的总步数。
第2~n-1行分别输入6条旋转规则中6个方位中的一个

输出描述
一行输出旋转过程中位于骰子上方的数字之和

样例输入

5
North
North
East
South
West

样例输出
21
数据范围及提示
对于100 %的数据 n≤1000


按题意模拟就好。我想多了,打的时候想弄出个骰子来,结果越弄越乱,胡搞了两个小时。

正解:

模拟。

#include<cstdio>#include<iostream>#include<cstring>#include<algorithm>#include<string>#include<queue>#include<cstdlib>using namespace std;const int max=0;int m,n,k,tot,ans=1,UP=1,DOWN=6,FRONT=2,BACK=5,LEFT=4,RIGNT=3;inline int read(){    int num;    char ch;    while((ch=getchar())<'0'||ch>'9');    num=ch-'0';    while((ch=getchar())>='0'&&ch<='9') num=num*10+ch-'0';    return num;}inline void out(int x){    if(x>=10) out(x/10);    putchar(x%10+'0');    return;}int main(){    freopen("touzi.in","r",stdin);    freopen("touzi.out","w",stdout);    n=read();    char c;    while((c=getchar())!=EOF)    {        if(c=='N')        {            int T=UP;            UP=FRONT,FRONT=DOWN,DOWN=BACK,BACK=T;            ans+=UP;        }        else if(c=='S')        {            int T=UP;            UP=BACK,BACK=DOWN,DOWN=FRONT,FRONT=T;            ans+=UP;         }        else if(c=='E')        {            int T=UP;             UP=LEFT,LEFT=DOWN,DOWN=RIGNT,RIGNT=T;            ans+=UP;        }        else if(c=='W')        {            int T=UP;            UP=RIGNT,RIGNT=DOWN,DOWN=LEFT,LEFT=T;            ans+=UP;        }        else if(c=='R')        {            int T=FRONT;            FRONT=RIGNT,RIGNT=BACK,BACK=LEFT,LEFT=T;            ans+=UP;        }        else if(c=='L')        {            int T=FRONT;            FRONT=LEFT,LEFT=BACK,BACK=RIGNT,RIGNT=T;            ans+=UP;        }    }    out(ans);    fclose(stdin);    fclose(stdout);    return 0;}

T2:

Problem 2 赛小城玩游戏

题目描述
众所周知,赛小城是一个游戏发烧友。
国庆节快到了,L国流行起了一种简单的扫雷游戏,这个游戏规则和扫雷一样,如果某个格子没有雷,那么它里面的数字表示和它8连通的格子里面雷的数目。现在棋盘是n×2的,第一列里面某些格子是雷,而第二列没有雷。
由于第一列的雷可能有多种方案满足第二列的数的限制,赛小城成功拿下所有记录之后,向你发下战书。你的任务即根据第二列的信息确定第一列雷有多少种摆放方案。

输入描述
第一行为N,第二行有N个数,依次为第二列的格子中的数。

输出描述
一个数,即第一列中雷的摆放方案数。

样例输入
2
1 1

样例输出
2

数据范围及提示
对于40 %的数据 1<= N <= 20
对于100 % 的数据 1<= N <= 10000


二分?DP?
看到题之后想打个DP,然后就想转移方程,最后边界不会处理,弃了。10分。
正解递推……我是真无语……

正解:

由某个点的前一点的数字和前两点的雷可以确定这个点是否放雷。

#include<cstdio>#include<iostream>#include<cstring>#include<algorithm>#include<string>#include<queue>#include<cstdlib>using namespace std;const int maxn=10005;int m,n,k,tot,ans=0,a[maxn];bool lei[maxn];inline int read(){    int num;    char ch;    while((ch=getchar())<'0'||ch>'9');    num=ch-'0';    while((ch=getchar())>='0'&&ch<='9') num=num*10+ch-'0';    return num;}inline void out(int x){    if(x>=10) out(x/10);    putchar(x%10+'0');    return;}void f(){    for(int i=3;i<=n;i++)    {        int t=0;        if(lei[i-2]==true)t++;        if(lei[i-1]==true)t++;        if(t>a[i-1]||t<a[i-1]-1)return;        if(t==a[i-1])continue;        if(t==a[i-1]-1)lei[i]=true;    }    int t=0;    if(lei[n-1]==true)t++;    if(lei[n]==true)t++;    if(a[n]==t)ans++;    return;}inline void init(){    memset(lei,0,sizeof(lei));}int main(){    freopen("mine.in","r",stdin);    freopen("mine.out","w",stdout);    n=read();    for(int i=1;i<=n;i++)        a[i]=read();    if(a[1]==0&&a[2]==0)    {        lei[1]=0,lei[2]=0;        f();    }    else if(a[1]==0&&a[2]==1)    {        lei[1]=0,lei[2]=0;        f();    }    else if(a[1]==1&&a[2]==1)    {        lei[1]=1,lei[2]=0;        f();        init();        lei[1]=0,lei[2]=1;        f();    }    else if(a[1]==1&&a[2]==2)    {        lei[1]=1,lei[2]=0;        f();        init();        lei[1]=0,lei[2]=1;        f();    }    else if(a[1]==2&&a[2]==2)    {        lei[1]=1,lei[2]=1;        f();    }    else if(a[1]==2&&a[2]==3)    {        lei[1]=1,lei[2]=1;        f();    }    else    {        out(0);        return 0;    }    out(ans);    fclose(stdin);    fclose(stdout);    return 0;}

T3:

Problem 3 赛小城学游泳

题目描述
众所周知,赛小城是一个胸怀大志,对游泳情有独钟的美男子。
他第一次尝试游泳便是在广州的大海边。不知怎的,在沙滩上,由于古老东方的神秘力量,他被吸入了一个新的海底聚落。召唤他的是南海龙王,因为他想为自己选定一个继承人。但管理海底世界需要一定的组织能力。于是他为赛小城出了一个题:若有n个城市和m条单向道路,城市编号为1~n。每条道路连接两个不同的城市,n和m满足m <= n(n - 1)。给定两个城市a和b,可以给a到b的所有简单路(所有城市最多经过一次,包括起点和终点)排序:先按长度从小到大排序,长度相同时按照字典序从小到大排序。管理南海一直是赛小城儿时的梦,他的任务便是求出从a城市到b城市的第k短路。
作为一名社会主义的好青年,助他一臂之力是你义不容辞的责任。

输入描述
输入的第一行为两个正整数 n 和 m,表示有 n 种化学物质和 m 条单向边。
接下来 m 行,每行有 3 个正整数 x,y,z,表示从化学物质x和化学物质y之间的单向边长度为 z
接下来一行,包括三个整数,a,b,k 表示赛小城所在的位置 a,终点所在的位置 b,和 k

输出描述
如果赛小城能通过第 k 短路从 S 到达 E,输出一个正整数,为第 k 短路的长度,如果不能通过第 k短路到达 E,输出“-1”(不包括引号)

样例输入
2 2
1 2 5
2 1 4
1 2 2

样例输出
14

数据范围及提示
对于 30%的数据 k <= 2
对于 70%的数据 1 <= N <= 100, 0 <= M <= 1000 1 <= a, b <= N, 1 <= c <= 100,k <= 100
对于 100%的数据 1 <= N <= 1000, 0 <= M <= 100000 1 <= a, b <= N, 1 <= c <= 100,k<=1000


k短路模板。

T4:

Problem 4 赛小城学数学

题目描述
众所周知,赛小城是一个爱打瞌睡的好学生。
这一天,他又在数学课上睡觉,这令数学老师忍无可忍。说是迟,那是快,数学老师一个箭步飞奔过去,敲醒了赛小城。并给出了一道极难的数学题,让他清醒一下。题意如下:从1 − N中找一些数乘起来使得答案是一个完全平方数,求这个完全平方数最大可能是多少。赛小城退役已久,码力不够犯了难。于是赛小城找到了你,作为一名OIer,你能帮帮他么?

输入描述
一个数 N

输出描述
一行一个整数代表答案对100000007取模之后的答案。

样例输入
7

样例输出
144

数据范围及提示
对于30%的数据,1≤N≤100。
对于50%的数据,1≤N≤5000。
对于70%的数据,1≤N≤〖10〗^5。
对于100%的数据,1≤N≤5×〖10〗^6。


数论,嗯,没有然后了。
分解质因数。

正解:

统计从1到N中每个质因数出现的次数,然后把每个质因数取它们的次数次幂(*还需要处理一下),然后相乘就是答案。

如样例:
1 2 3 4 5 6 7
其中,4=2*2 ;6=2*3 ;
质数有:2,3,5,7;

对应出现的次数:

2 -> 4(次)
3 -> 2(次)
5 -> 1(次)
7 -> 1(次)

*如果次数是奇数,则 次数– ,如果次数是偶数,则不变。

处理后得:
2 -> 4
3 -> 2
5 -> 0
7 -> 0

相乘得:(2^4)(3^2)(5^0)*(7^0)=144;

首先筛一下素数,然后对于1~N的每个数x,出现的次数可记为:f(x)=(N/x)+(N/x^2)+(N/x^3)+…+(N/x^k);

由此,可快速求得f(x);
然后快速幂、相乘、%,即可。

#include<cstdio>#include<iostream>#include<cstring>#include<algorithm>#include<string>#include<queue>#include<cstdlib>#define LL unsigned long longusing namespace std;const LL maxn=5000005,MOD=100000007;LL m,n,k,tot,ans=1;bool su[maxn];inline LL read(){    LL num;    char ch;    while((ch=getchar())<'0'||ch>'9');    num=ch-'0';    while((ch=getchar())>='0'&&ch<='9') num=num*10+ch-'0';    return num;}inline void out(LL x){    if(x>=10) out(x/10);    putchar(x%10+'0');    return;}inline LL pow(LL a,LL b){    LL base=a,r=1;    while(b)    {        if(b&1)        {            r=((r%MOD)*(base%MOD))%MOD;        }        base=((base%MOD)*(base%MOD))%MOD;        b>>=1;    }    return r;}void shai(LL p){    su[1]=false;    for(int i=2;i<=p;i++)        if(su[i])            for(int j=2;i*j<=n;j++)                su[i*j]=false;    return;}LL f(int x){    LL t=0,kk=x;    while(kk<=n)    {        t+=n/kk;        kk*=x;    }    return t;}int main(){    freopen("pow.in","r",stdin);    freopen("pow.out","w",stdout);    memset(su,1,sizeof(su));    n=read();    shai(n/2+1);    LL q=n/2+1;    for(LL i=1;i<=q;i++)        if(su[i])        {            k=f(i);            if(k%2==1)k--;            ans=((ans%MOD)*(pow(i,k)%MOD))%MOD;            while(ans>=MOD)ans-=MOD;        }    cout<<ans;    fclose(stdin);    fclose(stdout);    return 0;}
原创粉丝点击