[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 |
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