[SinGuLaRiTy] Nescafe 24杯模拟赛

【SinGularLaRiTy-1044】 Copyright (c) SinGuLaRiTy 2017. All Rights Reserved.

 

小水塘(lagoon)

题目描述

忘川沧月的小水塘的水面是一片由以下两种图形组成的图案:

<图lagoon-1>

这两种图形都由一个边长为2的正方形和两个半径为1的1/4圆组成,圆心在正方形的两个对角顶点上。
小水塘左上角坐标为(0,0),右下角坐标为(2*n,2*m)。水面上每一个顶点坐标为偶数的2*2正方形,都是上面两个图形中的一种。如果我们往水塘中的某个位置倒一桶污水,那么这桶污水会像画图中的油漆桶一样扩散开来,占据一片连续的区域,但是在线条边界处会停止扩散。注意如果倒在了线条上,扩散面积为0。
如下图所示,就是一个由4行4列上述图形组成的、左上角坐标(0,0)、右下角坐标(8,8)、某些位置倒了污水的水塘(白色部分为线条边界,线条实际宽度认为是0,为了明显、美观,此处加粗显示):

<图lagoon-2>

现在给出一个n行m列的由上述两种图形组成的水塘,起初水塘中全部为净水。给定q个往某个坐标上(x,y)倾倒污水的操作,对于每次操作,请求出在(x,y)上倾倒的污水最终会扩散多大的面积。

输入格式

第一行两个整数n、m。
接下来n行每行m个整数,每个整数是0或者1,中间没有空格隔开。0代表此处是<图lagoon-1>中左侧那个2*2的图形,1代表此处是右侧那个图形。例如<图lagoon-2>中的第一行用“0001”表示。
第n+2行是一个整数q。
接下来q行每行两个用空格隔开的整数x、y,表示这一次倾倒污水的坐标。

输出格式

对于每个询问,输出此次倾倒的污水最终扩散的面积,四舍五入保留4位小数。

样例数据

样例输入1 样例输出1
1 2
0 1
4
0 0
2 0
0 1
0 2
0.7854
4.8584
0.0000
4.8584
样例输入2 样例输出2
3 1
1
0
1
2
3 1
4 2
7.2876
1.5708

 

 

 

 

 

 

 

 

 

 

 

 

 

<数据范围>

对于 100% 的数据,1<=n,m,q<=100,0<=x<=2*n,0<=y<=2*m。

解析

看到数据范围很小,自然地考虑用搜索。由于只有两种图案,若进行搜索,需要考虑 2*4=8 种可能的情况。需要注意的是,如图所示,污水若覆盖了A,那么污水可能覆盖了B,也可能没有覆盖B——这就意味着要把这两个区域的vis访问情况分开进行记录。(这题的if串也是没的说了)

Code

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>

using namespace std;

const double pi=acos(-1.0);
const double big=4-0.5*pi;
const double small=0.25*pi;

int map[101][101];
int col[101][101][3]={0};
int list[501][501];

double all[10001];

struct P{
    int x,y,k;
}now;
queue<P> q;

int n,m,qq;

inline void flod(int x,int y,int k,int cnt)
{
    now.x=x;
    now.y=y;
    now.k=k;
    q.push(now);
    while(!q.empty())
    {
        now=q.front();
        q.pop();
        if(col[now.x][now.y][now.k])
            continue;
        col[now.x][now.y][now.k]=cnt;
        if(now.k!=1)
            all[cnt]+=small;
        else
            all[cnt]+=big;
        if(map[now.x][now.y]==0)
        {
            if(now.k==0)
            {
                if(now.x-1)
                {
                    if(map[now.x-1][now.y]==0)
                        q.push((P){now.x-1,now.y,1});
                    else
                        q.push((P){now.x-1,now.y,2});
                }
                if (now.y-1)
                {
                    if(map[now.x][now.y-1]==0)
                        q.push((P){now.x,now.y-1,1});
                    else
                        q.push((P){now.x,now.y-1,0});
                }
            }
            if(now.k==1)
            {
                if(now.x-1)
                {
                    if(map[now.x-1][now.y]==0)
                        q.push((P){now.x-1,now.y,2});
                    else
                        q.push((P){now.x-1,now.y,1});
                }
                if (now.y-1)
                {
                    if(map[now.x][now.y-1]==0)
                        q.push((P){now.x,now.y-1,2});
                    else
                        q.push((P){now.x,now.y-1,1});
                }
                if(now.x+1<=n)
                {
                    if(map[now.x+1][now.y]==0)
                        q.push((P){now.x+1,now.y,0});
                    else
                        q.push((P){now.x+1,now.y,1});
                }
                if (now.y+1<=m)
                {
                    if(map[now.x][now.y+1]==0)
                        q.push((P){now.x,now.y+1,0});
                    else
                        q.push((P){now.x,now.y+1,1});
                }
            }
            if(now.k==2)
            {
                if(now.x+1<=n)
                {
                    if(map[now.x+1][now.y]==0)
                        q.push((P){now.x+1,now.y,1});
                    else
                        q.push((P){now.x+1,now.y,0});
                }
                if(now.y+1<=m)
                {
                    if(map[now.x][now.y+1]==0)
                        q.push((P){now.x,now.y+1,1});
                    else
                        q.push((P){now.x,now.y+1,2});
                }
            }
        }
        else
        {
            if(now.k==0)
            {
                if(now.x-1)
                {
                    if(map[now.x-1][now.y]==0)
                        q.push((P){now.x-1,now.y,2});
                    else
                        q.push((P){now.x-1,now.y,1});
                }
                if(now.y+1<=m)
                {
                    if(map[now.x][now.y+1]==0)
                        q.push((P){now.x,now.y+1,0});
                    else
                        q.push((P){now.x,now.y+1,1});
                }
            }
            if(now.k==1)
            {
                if(now.x-1)
                {
                    if(map[now.x-1][now.y]==0)
                        q.push((P){now.x-1,now.y,1});
                    else
                        q.push((P){now.x-1,now.y,2});
                }
                if(now.y-1)
                {
                    if(map[now.x][now.y-1]==0)
                        q.push((P){now.x,now.y-1,1});
                    else
                        q.push((P){now.x,now.y-1,0});
                }
                if(now.x+1<=n)
                {
                    if(map[now.x+1][now.y]==0)
                        q.push((P){now.x+1,now.y,1});
                    else
                        q.push((P){now.x+1,now.y,0});
                }
                if(now.y+1<=m)
                {
                    if(map[now.x][now.y+1]==0)
                        q.push((P){now.x,now.y+1,1});
                    else
                        q.push((P){now.x,now.y+1,2});
                }
            }
            if(now.k==2)
            {
                if(now.x+1<=n)
                {
                    if(map[now.x+1][now.y]==0)
                        q.push((P){now.x+1,now.y,0});
                    else
                        q.push((P){now.x+1,now.y,1});
                }
                if(now.y-1)
                {
                    if(map[now.x][now.y-1]==0)
                        q.push((P){now.x,now.y-1,2});
                    else
                        q.push((P){now.x,now.y-1,1});
                }
            }
        }
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;++i)
        for (int j=1;j<=m;++j)
        {
            char ch;ch=getchar();
            while(ch!='1'&&ch!='0')
                ch=getchar();
            map[i][j]=ch-'0';
        }
    scanf("%d",&qq);
    int cnt=0;
    for(int i=1;i<=n;++i)
        for(int j=1;j<=m;++j)
            for(int k=0;k<=2;++k)
                if(!col[i][j][k])
                    flod(i,j,k,++cnt);
    for(int i=1;i<=n;++i)
        for(int j=1;j<=m;++j)
        {
            int xx=i-1,yy=j-1;
            if (map[i][j]==0)
            {
                list[xx*2][yy*2]=col[i][j][0];
                list[xx*2+1][yy*2+1]=col[i][j][1];
                list[xx*2+2][yy*2]=col[i][j][1];
                list[xx*2][yy*2+2]=col[i][j][1];
                list[xx*2+2][yy*2+2]=col[i][j][2];
            }
            if (map[i][j])
            {
                list[xx*2][yy*2]=col[i][j][1];
                list[xx*2+1][yy*2+1]=col[i][j][1];
                list[xx*2+2][yy*2+2]=col[i][j][1];
                list[xx*2+2][yy*2]=col[i][j][2];
                list[xx*2][yy*2+2]=col[i][j][0];
            }
        }
    while (qq--)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        if((x%2)!=(y%2))
        {
            printf("0.0000\n");
            continue;
        }
        printf("%.4f\n",all[list[x][y]]);
    }
}

颂芬梭哈(ptgiving)

题目描述

Alice 和 Mukyu 最近偶然得到了一本写有一种叫做梭哈的扑克游戏的规则的说明书(名为《C████████nd》,中间部分被涂掉了),据其所述,梭哈是一种使用黑桃、红心、梅花、方片的 A 到 K 共 52 张牌(没有大小王)来进行的扑克牌游戏。
不幸的是,规则说明中有关整个游戏的进行方式的部分被撕掉了,Alice 和 Mukyu 从残存的部分只得知了“手牌上限是 5 张”这一消息,所以他们决定每次直接给两人各发 5 张牌,判定谁的手牌比较大,说明书中关于手牌大小判定的信息如下:

所有五张牌的组合,按以下秩序,由大至小排行分为不同牌型:
1、同花顺(Straight Flush):同一花色,顺序的牌。 例: Q♦ J♦ 10♦ 9♦ 8♦;
2、四条(Four of a Kind):有四张同一点数的牌。 例: 10♣ 10♦ 10♥ 10♠ 9♥;
3、满堂红(Full House):三张同一点数的牌,加一对其他点数的牌。 例: 8♣ 8♦ 8♠ K♥ K♠;
4、同花(Flush):五张同一花色的牌。 例: A♠ K♠ 10♠ 9♠ 8♠;
5、顺子(Straight):五张顺连的牌。 例: K♦ Q♥ J♠ 10♦ 9♦;
6、三条(Three of a kind):有三张同一点数的牌。 例: J♣ J♥ J♠ K♦ 9♠;
7、两对(Two Pairs):两张相同点数的牌,加另外两张相同点数的牌。 例: A♣ A♦ 8♥ 8♠ Q♠;
8、一对(One Pair):两张相同点数的牌。 例: 9♥ 9♠ A♣ J♠ 8♥;
9、无对(Zilch):不能排成以上组合的牌,以点数决定大小。例: A♦ Q♦ J♠ 9♣ 8♣。
若牌型一样则利用点数和花色决定胜负。(点数优先)
点数的顺序(从大至小)为:A>K>Q>J>10>9>8>7>6>5>4>3>2。(注:当 5 张手牌是 5
4 3 2 A 的时候,A 可以看作最小的牌,此时的牌型仍然为顺子,是顺子里面最小的一个)。
花色的顺序(大至小)为:黑桃(♠)>红心(♥)>梅花(♣)>方块(♦)。
举例说明:
1、Q♦ J♦ 10♦ 9♦ 8♦ > 8♣ 8♥ 8♠ K♥ K♠ (前者牌型为同花顺,比后者大);
2、9♣ 9♦ 9♠ Q♥ Q♠ > 8♣ 8♦ 8♠ K♥ K♠ (两者牌型均为满堂红,比较牌型中三张同一点数的牌 9 比 8 大);
3、A♣ A♦ 8♥ 8♠ Q♠ > A♠ A♥ 7♥ 7♠ K♠ (两者牌型均为两对,且最大的对子相同,此时比较次大的对子,8 比 7 大);
4、A♠ Q♠ J♥ 9♥ 8♥ > A♦ Q♦ J♠ 9♣ 8♣ (两者牌型均为无对,所有数码均相同,此时比较最大牌的花色,A♠ > A♦)。
5、4♠ 4♥ A♦ Q♦ 5♦ > 4♣ 4♦ A♠ Q♠ 5♠ (两者牌型均为一对,所有数码均相同,此时对 4 为牌型里最大的部分,因此比较 4♠ > 4♣)

尽管 Alice 和 Mukyu 都可以轻易的判断出结果,他们还是想见识一下现代科技的力量。

输入格式

第一行包含一个正整数 N,表示有 N 组测试数据。
每组测试数据包含 10 行,前 5 行每行用两个整数描述一张 Alice 手上的牌,第一个数表示牌的数码(1 表示 A,13 表示 K),第二个数表示牌的花色(1 表示黑桃,2 表示红心, 3 表示梅花,4 表示方块)。
后 5 行每行用两个整数描述 Mukyu 手上的牌,格式同上。

输出格式

对于每组测试数据,在单独的一行内输出 Alice 或 Mukyu,表示谁能赢。

样例数据

样例输入 样例输出

1
1 3
5 3
4 3
3 3
2 3
6 1
10 4
7 1
8 1
9 2

Alice

 

 

 

 

 

 

 

 

 

 

 

<样例解释>

Alice 的手牌构成同花顺,而 Mukyu 的手牌仅构成普通顺子。

<数据范围>

对于 10%的数据,保证输入的全部牌型都是无对。
对于另外 30%的数据,保证输入的全部牌型都是顺子、同花或同花顺。
对于 100%的数据,保证 N ≤ 100000。
C++选手如果使用 cin 读入数据很可能因此超时,推荐使用 scanf/printf。

解析

模拟:一大堆 if串+函数 考虑每一种牌型比较的情况。

Code

#include<iostream> 
#include<cstdio> 
#include<cstring> 
#include<algorithm> 

#define num first 
#define col second 
#define mp make_pair 

using namespace std; 

typedef pair<int,int> pii; 
const int N=5+5; 

int cnt[20]; 

inline void getint(int&num){ 
    char c;num=0; 
    while((c=getchar())<'0'||c>'9'); 
    while(c>='0'&&c<='9'){num=num*10+c-48;c=getchar();} 
} 

int T;pii Ail[N],Muk[N]; 
bool cmp(pii a,pii b){ 
    if(a.num==b.num) 
        return a.col>b.col; 
    else return a.num<b.num; 
} 
bool isone(pii *arr){//同花顺 
    memset(cnt,0,sizeof cnt); 
    for(int i=1;i<=5;i++){ 
        if(arr[i].col!=arr[1].col) 
            return 0; 
        cnt[arr[i].num]++; 
        if(arr[i].num==1) 
            cnt[14]++; 
    } 
    for(int i=1;i<=10;i++) 
        if(cnt[i]==1&&cnt[i+1]==1&&cnt[i+2]==1&&cnt[i+3]==1&&cnt[i+4]==1) 
            return 1; 
    return 0; 
} 
bool istwo(pii *arr){//四条 
    bool f=1; 
    for(int i=2;i<=4;i++) 
        if(arr[i].num!=arr[1].num){ 
            f=0;break ; 
        } 
    if(f) return 1; 
    f=1; 
    for(int i=3;i<=5;i++) 
        if(arr[i].num!=arr[2].num){ 
            f=0;break ; 
        } 
    return f; 
} 
bool isthree(pii *arr){//满堂红 
    if(arr[1].num==arr[2].num&&arr[1].num==arr[3].num&&arr[4].num==arr[5].num) 
        return 1; 
    if(arr[1].num==arr[2].num&&arr[3].num==arr[4].num&&arr[3].num==arr[5].num) 
        return 1; 
    return 0; 
} 
bool isfour(pii *arr){//同花 
    for(int i=2;i<=5;i++) 
        if(arr[i].col!=arr[1].col) 
            return 0; 
    return 1; 
} 
bool isfive(pii *arr){//顺子 
    memset(cnt,0,sizeof cnt); 
    for(int i=1;i<=5;i++){ 
        cnt[arr[i].num]++; 
        if(arr[i].num==1) 
            cnt[14]++; 
    } 
    for(int i=1;i<=10;i++) 
        if(cnt[i]==1&&cnt[i+1]==1&&cnt[i+2]==1&&cnt[i+3]==1&&cnt[i+4]==1) 
            return 1; 
    return 0; 
} 
bool issix(pii *arr){//三条 
    if(arr[1].num==arr[2].num&&arr[1].num==arr[3].num) 
        return 1; 
    if(arr[2].num==arr[3].num&&arr[2].num==arr[4].num) 
        return 1; 
    if(arr[3].num==arr[4].num&&arr[3].num==arr[5].num) 
        return 1; 
    return 0; 
} 
bool isseven(pii *arr){//两对 
    memset(cnt,0,sizeof cnt); 
    for(int i=1;i<=5;i++) 
        cnt[arr[i].num]++; 
    int tot=0; 
    for(int i=1;i<=13;i++) 
        if(cnt[i]==2) tot++; 
    return tot==2; 
} 
bool iseight(pii *arr){//一对 
    for(int i=2;i<=5;i++) 
        if(arr[i].num==arr[i-1].num) 
            return 1; 
    return 0; 
} 
int check(pii *arr){ 
    if(isone(arr)) return 1; 
    else if(istwo(arr)) return 2; 
    else if(isthree(arr)) return 3; 
    else if(isfour(arr)) return 4; 
    else if(isfive(arr)) return 5; 
    else if(issix(arr)) return 6; 
    else if(isseven(arr)) return 7; 
    else if(iseight(arr)) return 8; 
    else return 9; 
} 
bool cmp1(pii *a,pii *b){//同花顺 
    bool f1=0,f2=0; 
    if(a[1].num==1&&a[5].num==13) f1=1; 
    else if(b[1].num==1&&b[5].num==13) f2=1; 
    if(f1!=f2) return f1; 
    if(f1&&f2) return a[1].col<b[1].col; 
      
    if(a[1].num==b[1].num) 
        return a[1].col<b[1].col; 
    else return a[1].num>b[1].num; 
} 
bool cmp2(pii *a,pii *b){//四条 
    int num_a1,num_a2,col_a; 
    if(a[1].num==a[2].num&&a[1].num==a[3].num&&a[1].num==a[4].num){ 
        num_a1=a[1].num,num_a2=a[5].num; 
        col_a=a[5].col; 
    } 
    else{ 
        num_a1=a[2].num,num_a2=a[1].num; 
        col_a=a[1].col; 
    } 
      
    int num_b1,num_b2,col_b; 
    if(b[1].num==b[2].num&&b[1].num==b[3].num&&b[1].num==b[4].num){ 
        num_b1=b[1].num,num_b2=b[5].num; 
        col_b=b[5].col; 
    } 
    else{ 
        num_b1=b[2].num,num_b2=b[1].num; 
        col_b=b[1].col; 
    } 
      
    if(num_a1==1) num_a1=14; 
    if(num_a2==1) num_a2=14; 
    if(num_b1==1) num_b1=14; 
    if(num_b2==1) num_b2=14; 
      
    if(num_a1!=num_b1) 
        return num_a1>num_b1; 
    else{ 
        if(num_a2!=num_b2) 
            return num_a2>num_b2; 
        else return col_a<col_b; 
    } 
} 
bool cmp3(pii *a,pii *b){//满堂红 
    for(int i=1;i<=5;i++) 
        if(a[i].num==1) a[i].num=14; 
    for(int i=1;i<=5;i++) 
        if(b[i].num==1) b[i].num=14; 
    sort(a+1,a+6,cmp); 
    sort(b+1,b+6,cmp); 
      
    int sta1,sta2,stb1,stb2; 
    if(a[1].num==a[2].num&&a[1].num==a[3].num)  
        sta1=1,sta2=4; 
    else sta1=3,sta2=1; 
      
    if(b[1].num==b[2].num&&b[1].num==b[3].num)  
        stb1=1,stb2=4; 
    else stb1=3,stb2=1; 
      
    for(int i=sta1+2,j=stb1+2;i>=sta1&&j>=stb1;i--,j--){ 
        if(a[i].num==b[j].num) continue ; 
        else return a[i].num>b[j].num; 
    } 
      
    for(int i=sta2+1,j=stb2+1;i>=sta2&&j>=stb2;i--,j--){ 
        if(a[i].num==1) a[i].num=14; 
        if(b[j].num==1) b[j].num=14; 
        else if(a[i].num==b[j].num) continue ; 
        else return a[i].num>b[j].num; 
    } 
      
    for(int i=sta1+2,j=stb1+2;i>=sta1&&j>=stb1;i--,j--){ 
        if(a[i].col==b[j].col) continue ; 
        else return  a[i].col<b[i].col; 
    } 
      
    for(int i=sta2+1,j=stb2+1;i>=sta2&&j>=stb2;i--,j--){ 
        if(a[i].col==b[j].col) continue ; 
        else return  a[i].col<b[i].col; 
    } 
      
    return 1; 
} 
bool cmp4(pii *a,pii *b){//同花 
    for(int i=1;i<=5;i++) 
        if(a[i].num==1) a[i].num=14; 
    for(int i=1;i<=5;i++) 
        if(b[i].num==1) b[i].num=14; 
    sort(a+1,a+6,cmp); 
    sort(b+1,b+6,cmp); 
    for(int i=5;i;i--){ 
        if(a[i].num==b[i].num) continue ; 
        return a[i].num>b[i].num; 
    } 
    for(int i=5;i;i--){ 
        if(a[i].col==b[i].col) continue ; 
        return a[i].col<b[i].col; 
    } 
    return 1; 
} 
bool cmp5(pii *a,pii *b){//顺子 
    if(a[1].num==1&&a[5].num==13){ 
        pii t=a[1];t.num=14; 
        for(int i=2;i<=5;i++) 
            a[i-1]=a[i]; 
        a[5]=t; 
    } 
    if(b[1].num==1&&b[5].num==13){ 
        pii t=b[1];t.num=14; 
        for(int i=2;i<=5;i++) 
            b[i-1]=b[i]; 
        b[5]=t; 
    } 
    /*for(int i=5;i;i--){ 
        if(a[i].num==b[i].num) continue ; 
        return a[i].num>b[i].num; 
    }*/
    if(a[1].num!=b[1].num) 
        return a[1].num>b[1].num; 
    for(int i=5;i;i--){ 
        if(a[i].col==b[i].col) continue ; 
        return a[i].col<b[i].col; 
    } 
    return 1; 
} 
bool cmp6(pii *a,pii *b){//三条 
    for(int i=1;i<=5;i++) 
        if(a[i].num==1) a[i].num=14; 
    for(int i=1;i<=5;i++) 
        if(b[i].num==1) b[i].num=14; 
    sort(a+1,a+6,cmp); 
    sort(b+1,b+6,cmp); 
      
    int sta; 
    for(int i=3;i<=5;i++) 
        if(a[i].num==a[i-1].num&&a[i].num==a[i-2].num){ 
            sta=i-2;break ; 
        } 
      
    int stb; 
    for(int i=3;i<=5;i++) 
        if(b[i].num==b[i-1].num&&b[i].num==b[i-2].num){ 
            stb=i-2;break ; 
        } 
      
    for(int i=sta+2,j=stb+2;i>=sta&&j>=stb;i--,j--){ 
        if(a[i].num==b[j].num) continue ; 
        else return a[i].num>b[j].num; 
    } 
      
    for(int i=5,j=5;i&&j;i--,j--){ 
        if(i==sta+2) i=sta-1; 
        if(j==stb+2) j=stb-1; 
        if(a[i].num==b[j].num) continue ; 
        else return a[i].num>b[j].num; 
    } 
      
    for(int i=sta+2,j=stb+2;i>=sta&&j>=stb;i--,j--){ 
        //printf("%d %d\n",a[i].col,b[j].col); 
        if(a[i].col==b[j].col) continue ; 
        else return a[i].col<b[j].col; 
    } 
      
    for(int i=5,j=5;i&&j;i--,j--){ 
        if(i==sta+2) i=sta-1; 
        if(j==stb+2) j=stb-1; 
        if(a[i].col==b[j].col) continue ; 
        else return a[i].col<b[j].col; 
    } 
    return 1; 
      
} 
bool cmp7(pii *a,pii *b){//两对 
    for(int i=1;i<=5;i++) 
        if(a[i].num==1) a[i].num=14; 
    for(int i=1;i<=5;i++) 
        if(b[i].num==1) b[i].num=14; 
    sort(a+1,a+6,cmp); 
    sort(b+1,b+6,cmp); 
      
    pii pa1[3],pa2[3],pb1[3],pb2[3]; 
    bool f1=0,f2=0; 
    bool v1[6],v2[6]; 
    memset(v1,0,sizeof v1); 
    memset(v2,0,sizeof v2); 
    for(int i=2;i<=5;i++){ 
        if(a[i].num==a[i-1].num){ 
            if(f1) pa1[1]=a[i],pa1[2]=a[i-1]; 
            else pa2[1]=a[i],pa2[2]=a[i-1],f1=1; 
            v1[i]=v1[i-1]=1; 
        } 
          
        if(b[i].num==b[i-1].num){ 
            if(f2) pb1[1]=b[i],pb1[2]=b[i-1]; 
            else pb2[1]=b[i],pb2[2]=b[i-1],f2=1; 
            v2[i]=v2[i-1]=1; 
        } 
    } 
    if(pa1[1].num!=pb1[1].num) 
        return pa1[1].num>pb1[1].num; 
      
    if(pa1[2].num!=pb1[2].num) 
        return pa1[2].num>pb1[2].num; 
      
    if(pa2[1].num!=pb2[1].num) 
        return pa2[1].num>pb2[1].num; 
      
    if(pa2[2].num!=pb2[2].num) 
        return pa2[2].num>pb2[2].num; 
      
    for(int i=1;i<=5;i++)if(!v1[i]) 
        for(int j=1;j<=5;j++)if(!v2[j]){ 
            if(a[i].num!=b[j].num)  
                return a[i].num>b[j].num; 
            break ; 
        } 
      
    if(pa1[1].col!=pb1[1].col) 
        return pa1[1].col<pb1[1].col; 
      
    if(pa1[2].col!=pb1[2].col) 
        return pa1[2].col<pb1[2].col; 
      
    if(pa2[1].col!=pb2[1].col) 
        return pa2[1].col<pb2[1].col; 
      
    if(pa2[2].col!=pb2[2].col) 
        return pa2[2].col<pb2[2].col; 
      
    for(int i=1;i<=5;i++)if(!v1[i]) 
        for(int j=1;j<=5;j++)if(!v2[j]){ 
            if(a[i].col!=b[j].col)  
                return a[i].col<b[j].col; 
            break ; 
        } 
    return 1; 
} 
bool cmp8(pii *a,pii *b){//一对 
    for(int i=1;i<=5;i++) 
        if(a[i].num==1) a[i].num=14; 
    for(int i=1;i<=5;i++) 
        if(b[i].num==1) b[i].num=14; 
    sort(a+1,a+6,cmp); 
    sort(b+1,b+6,cmp); 
      
    int sta; 
    for(int i=2;i<=5;i++) 
        if(a[i].num==a[i-1].num){ 
            sta=i-1;break ; 
        } 
      
    int stb; 
    for(int i=2;i<=5;i++) 
        if(b[i].num==b[i-1].num){ 
            stb=i-1;break ; 
        } 
      
    for(int i=sta+1,j=stb+1;i>=sta&&j>=stb;i--,j--){ 
        if(a[i].num==b[j].num) continue ; 
        else return a[i].num>b[j].num; 
    } 
      
    for(int i=5,j=5;i&&j;i--,j--){ 
        if(i==sta+1) i=sta-1; 
        if(j==stb+1) j=stb-1; 
        if(a[i].num==b[j].num) continue ; 
        else return a[i].num>b[j].num; 
    } 
      
    for(int i=sta+1,j=stb+1;i>=sta&&j>=stb;i--,j--){ 
        //printf("%d %d\n",a[i].col,b[j].col); 
        if(a[i].col==b[j].col) continue ; 
        else return a[i].col<b[j].col; 
    } 
      
    for(int i=5,j=5;i&&j;i--,j--){ 
        if(i==sta+1) i=sta-1; 
        if(j==stb+1) j=stb-1; 
        if(a[i].col==b[j].col) continue ; 
        else return a[i].col<b[j].col; 
    } 
    return 1; 
} 
bool cmp9(pii *a,pii *b){//无对 
    if(a[1].num==1){ 
        pii t=a[1];t.num=14; 
        for(int i=2;i<=5;i++) 
            a[i-1]=a[i]; 
        a[5]=t; 
    } 
    if(b[1].num==1){ 
        pii t=b[1];t.num=14; 
        for(int i=2;i<=5;i++) 
            b[i-1]=b[i]; 
        b[5]=t; 
    } 
    for(int i=5;i;i--){ 
        if(a[i].num==b[i].num) continue ; 
        else return a[i].num>b[i].num; 
    } 
    for(int i=5;i;i--){ 
        if(a[i].col==b[i].col) continue ; 
        else return a[i].col<b[i].col; 
    } 
    return 1; 
} 
int main(){ 
    getint(T); 
    while(T--){ 
        for(int i=1;i<=5;i++) 
            getint(Ail[i].num),getint(Ail[i].col); 
        for(int i=1;i<=5;i++) 
            getint(Muk[i].num),getint(Muk[i].col); 
        sort(Ail+1,Ail+6,cmp); 
        sort(Muk+1,Muk+6,cmp); 
        int t1=check(Ail); 
        int t2=check(Muk); 
        if(t1==t2){ 
            bool win; 
            if(t1==1) win=cmp1(Ail,Muk); 
            else if(t1==2) win=cmp2(Ail,Muk); 
            else if(t1==3) win=cmp3(Ail,Muk); 
            else if(t1==4) win=cmp4(Ail,Muk); 
            else if(t1==5) win=cmp5(Ail,Muk); 
            else if(t1==6) win=cmp6(Ail,Muk); 
            else if(t1==7) win=cmp7(Ail,Muk); 
            else if(t1==8) win=cmp8(Ail,Muk); 
            else if(t1==9) win=cmp9(Ail,Muk); 
            printf("%s\n",win?"Alice":"Mukyu"); 
        } 
        else printf("%s\n",t1<t2?"Alice":"Mukyu"); 
    } 
} 

周年纪念(anniversary)

题目描述

距离著名意大利数学家 Fibonacci 的 900 年诞辰纪念日还剩下不到 60 年。当然,这种重要的纪念日需要很多准备。

Sidepi 认为应当解决以下问题来表达对 Fibonacci 的纪念:给定由 l、l+1、l+2……r 这 r-l+1 个整数构成的集合 A,考虑 A 的所有含有 k 个元素的子集;对于每个子集 B,设 Bi 是 能整除子集中全部 k 个元素的最大整数;i 是所有 Bi 的最大值,求第 i 个 Fibonacci 数 F[i] 是多少。 当然,Sidepi 也没忘记提醒你,F[1]=1,F[2]=1,F[n]=F[n-1]+F[n-2](n>=3)。 Sidepi 有半个多世纪的时间来解决这个问题,但是你只有 3 个半小时。因此你只需要输出 F[i] mod m 的值。

输入格式

四个用空格隔开的整数 m、l、r、k。 

输出格式

上述问题的答案 F[i] mod m 的值。 

样例数据

样例输入 样例输出
10 1 8 2 3

 

 

<数据范围>

对于 50% 的数据,1<=l,r<=10^6;对于 100% 的数据,1<=m<=10^9,1 ≤ l < r ≤ 10^12,2 ≤ k ≤ r - l + 1。 

解析

[l,r]间i的倍数的个数等于r/i-(l-1)/i,随着i的增大r/i是减小的,(l-1)/i也是减小的,通过感觉我们知道r/i-(l-1)/i大体上也是减小的,但并不是严格递减,即使用二分+暴力也不能很有效地减小这个范围
注意到从1开始一个个地枚举i是很不明智的,因为即使i++也很有可能不会使r/i和(l-1)/i中任意一项的值改变
所以可以想到对于i来说min(l/(l/i),r/(r/i))是在保证r/i和(l-1)/i不变前提下的更优值,所以我们每次都只用枚举r/i和(l-1)/i一定时i的最优值即可,然后i++如此往复计算出下一个状态的最优值,可以证明在这个过程中我们一定会遍历到使r/i-(l-1)/i>=k成立最大的那个i
这个做法很容易想出来,但是时间复杂度怎么保证呢……
不妨假设在最gg的情况l=r=1e12,k=1
那么i=1,2,3……r/3,r/2,r
注意由于i只能为整数,所以i在一开始是很连续的,但是往后开始就不连续了,我们只要把这个临界点计算出来,然后就可以分段计算出时间复杂度了。

我们可以假设第x次以及以后的分割都是按间隔为1均匀地分布的。
n/x-n/(x-1)=1
n*(x+1)=x*(x+1)+n*x
n=x*(x+1)
x=sqrt(n)
时间复杂度:O(2*sqrt(n))

Code

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>

using namespace std;

typedef long long ll;

struct Mat{
    ll s[2][2];
    ll* operator [](const ll a){
        return s[a];
    }
};
Mat cv={0,1,1,1};
Mat fib={0,1,0,0};

ll m,l,r,w,x=1,y;
Mat mul(Mat a,Mat b)
{
    Mat s={0,0,0,0};
    for(ll i=0;i<2;i++)
        for(ll j=0;j<2;j++)
            for(ll k=0;k<2;k++)
                s[i][j]+=a[i][k]*b[k][j]%m;
    return s;
}
Mat power(Mat a,ll b)
{
    Mat s={1,0,0,1};
    while(b)
    {
        if(b&1)
            s=mul(s,a);
        a=mul(a,a);
        b/=2;
    }
    return s;
}
int main()
{
    cin>>m>>l>>r>>w;
    l--;
    while(x<=r)
    {
        if((l/x)==0)
            x=r/(r/x);
        else
            x=min(l/(l/x),r/(r/x));
        if(r/x-l/x>=w)
            y=x;
        x++;
    }
    cv=power(cv,y);
    fib=mul(fib,cv);
    cout<<fib[0][0]<<endl;
    return 0;
}

 

Time: 2017-10-29

posted @ 2017-10-29 17:02  SinGuLaRiTy2001  阅读(432)  评论(0编辑  收藏  举报