双重加密(pswd)

Background

据说,Fish的信又被破译了……

Description

Fish对用最优前缀编码来加密信还是不够放心,他决定加个双保险。

Fish写了一封加双保险的信给某人。还没来得及告诉他(她?)解密方法,TA就急不可耐地来问Fish了。

这封信由两部分组成,前一部分是正文(当然已经用最优前缀编码加密过),后一部分包含n行,每行有m非负整数

Fish告诉TA,解密这封信需要一个密钥。设第i行的数是a[i][1],a[i][2],…,a[i][m],对于每一个i,均满足(a[i][1]+a[i][2]+…+a[i][m-1]) mod K = a[i][m]的最大的K即是密钥。

TA很想知道Fish写给TA的内容,于是TA请你帮忙求出这个K。如果这个K不存在的话,也要告诉TATA会把FishK了。

Input

输入第一行为n

对于接下来的n行,每行第一个整数为m,之后包含m个正整数,即该行的内容。

Output

输出一行,包含一个正整数,即密钥K,如果K不存在,输出-1

Example

pswd.in

2

2 5 1

2 7 1

pswd.out

2

 

Constraints

对于30%的数据,n,m ≤ 10,输入中的所有正整数小于等于100

对于100%的数据,n ≤ 10000, m ≤ 200 输入中的所有正整数小于等于10000000

输入保证m ≥ 2

C++ Code
#include <cstdio>
int n;
int m;
int t;
int a[10100];
void swap(int &a,int &b){int c=a;a=b;b=c;}
/*
int gcd(int a,int b){
if (a>b) swap(a,b);
if (a==0) return b;
return gcd(b % a,a);
}
*/
int gcd(int a,int b){
if (a>b) swap(a,b);
while (a!=0){
int c=b % a;
b=a;
a=c;
}
return b;
}
int main(){
freopen("pswd.in","r",stdin);
freopen("pswd.out","w",stdout);
scanf("%d",&n);
for (int i=1;i<=n;i++){
scanf("%d",&m);
int x;
int tot=0;
for (int j=1;j<m;j++){
scanf("%d",&x);
tot+=x;
}
scanf("%d",&x);
a[i]=x;
tot-=x;
if (i==1) t=tot;else t=gcd(t,tot);
}
for (int i=1;i<=n;i++){
if (t<=a[i]){
printf("-1\n");
return 0;
}
}
printf("%d",t);
return 0;
}


海山战役(Hyjal)

Background

Lkwmm从梦中拉回了现实……

打开电脑,进入魔兽战役,重回海山之巅。苍茫的天空下,世界之树闪着格外耀眼的光芒,海加尔山翠绿的丛林里,无数小精灵静静地,等待着最后的时刻。阿克蒙德率领这燃烧军团发起了潮水般进攻。人类,部落,精灵,或互为陌路,或曾植仇恨,然而也许是为了尊严与荣耀,也许仅仅是为了捍卫家园,他们齐心协力,并肩作战,用自己的身躯延缓着燃烧军团邪恶的冲锋。当阿克蒙德终于越过三族阵地,到达世界之树时,玛法里奥吹响了最后的号角,成千上万的精灵之魂与阿克蒙德、世界之树一同湮灭在海山那耀眼的翠绿中。三族将士用自己的鲜血在海加尔山上镌刻下了一座永恒的圣碑……

这是一幅多么悲壮的画卷啊。不过Lkw很懊恼,因为他卡在了某波进攻上……

Description

Lkw面对的这波进攻中,燃烧军团的兵力包括numX个地狱火和numY条冰霜巨龙,地狱火和冰霜巨龙都拥有HP点生命值。Lkw的军队包含弓箭手和女猎手两种士兵,由于女猎手只能对地,所以Lkw决定派女猎手去攻击地狱火而派弓箭手去攻击冰霜巨龙。

女猎手、弓箭手在每一轮进攻中均对敌方单位造成1点伤害。每一轮进攻先由Lkw发起,Lkw可以自由选择每个单位攻击的目标,如果地狱火或冰龙的HP降到0,则被认为死亡,之后,每个地狱火会杀死attack个女猎手,同样冰龙会杀死attack个弓箭手。

假设Lkw可以建造limit人口的军队,每个弓箭手和女猎手均占一个人口,军队比例可以随意指定。Lkw想尽早结束战斗以便进行下一波的防御,请你告诉他最少需要几回合消灭敌军,或者干脆说,这是不可能完成的任务。

Input

输入共五行,每行包含一个正整数,分别表示limit,HP,attack,numX,numY

Output

输出一个正整数,即消灭敌军最小的回合数。如果无法消灭敌军,输出-1

Example

hyjal.in

7

2

1

2

3

 

hyjal.out

2

 

Constraints

对于30%的数据 limit ≤ 500HP,attack,numX,numY ≤ 100

对于100%的数据 limit ≤ 1000000000HP,attack,numX,numY ≤ 40000


C++
#include <cstdio>
#include <cstring>
#define INF 20000000
__int64 limit,attack,numx,numy,hp;
__int64 l,r,mid;
__int64 sx,sy;
int flag1,flag2;
int min(int a,int b){return a<b?a:b;}
int max(int a,int b){return a>b?a:b;}
int getx(__int64 x){
int len=0;
while (sx && x){
len++;
if (x<=sx) sx-=x;else sx=0;
__int64 att=((sx / hp)+((sx % hp)!=0))*attack;
if (att<=x) x-=att;else x=0;
}
if (sx==0) return len;
return -1;
}
int gety(__int64 x){
int len=0;
while (sy && x){
len++;
if (x<=sy) sy-=x;else sy=0;
__int64 att=((sy / hp)+((sy % hp)!=0))*attack;
if (att<=x) x-=att;else x=0;
}
if (sy==0) return len;
return -1;
}
void check(){
sx=hp*numx;
flag1=getx(mid);
sy=hp*numy;
flag2=gety(limit-mid);
}
int main(){
freopen("hyjal.in","r",stdin);
freopen("hyjal.out","w",stdout);
scanf("%I64d%I64d%I64d%I64d%I64d",&limit,&hp,&attack,&numx,&numy);
l=0,r=limit;
int ans=INF;
while (l<r){
mid=(l + r) >> 1;
check();
if (flag1!=-1 && flag2!=-1) ans=min(ans,max(flag1,flag2));
if (flag1==-1) l=mid+1;else if (flag2==-1) r=mid;
else if (flag1>flag2) l=mid+1;else r=mid;
}
if (ans>=INF >> 2){
printf("-1\n");
return 0;
}
printf("%d\n",ans);
return 0;
}


生日舞会(Party)

Background

Bright终于吃完了他心爱的芒果……

Description

晚餐过后,生日晚会的重头戏——舞会即将拉开帷幕。参加舞会的N名同学将被分成几组,不同组之间每两人都会跳一支舞,同一组内人之间则不会跳舞。

分组的工作当然由Bright来完成。Bright要考虑的东西有很多,比如要给XXXXXX创造一个亲密的空间,比如得把XXXXXX放在一组以免不和谐的音符,比如要把自己和……至于还有多少个比如就不得而知了,我们只知道当Bright自豪地欣赏自己精心制作的分组表时发现了一个严重的问题:糟糕,今天舞会可没有这么多的时间……”

由于舞会时间有限,同时不能有太多的空余,Bright希望舞会中恰好跳K支舞。先前的芒果大餐实在耗费了太多的时间,Bright只好求助于你,你能帮助他么?

Input

每个测试点包含多组测试数据。

每组数据包含两个正整数N,K

 

Output

对于每组测试数据,如果有可行的安排,恰好跳K支舞,输出“Yes”,否则输出“No(不包括引号)

Example

party.in

2 0

2 1

3 1

3 2

 

party.out

Yes

Yes

No

Yes

Constraints

对于30%的数据 N ≤ 10K ≤ 40

对于50%的数据 N ≤ 50

对于100%的数据 N ≤ 200K < 231

每个测试点中至多有10组测试数据

C++
#include <iostream>
#include <cstdio>
using namespace std;
int f[201][20000];
int n,k;
int main(){
freopen("party.in","r",stdin);
freopen("party.out","w",stdout);
for (int i=1;i<=200;i++) f[i][0]=1;
for (int i=1;i<=200;i++){
for (int j=0;j<=19900;j++){
if (f[i][j]){
for (int k=0;k<=200-i;k++)
if (j+i*k<=19900) f[i+k][j+i*k]=1;
}
}
}
while (cin>>n>>k){
if (k>=19900) printf("No\n");
else{
if(f[n][k]) printf("Yes\n");
else printf("No\n");
}
}
return 0;
}


KNim(NimForK)

Background

Xxy开始讲经典的Nim游戏了……

不过这次游戏将会有K人参与。刚读完题,未来的某位神牛便提出了自己的策略,他想请你模拟一下,以便他提出更为高深的策略。

Description

在这个游戏中,K人围坐在一张圆桌上,按照顺时针方向依次编号为1-K。游戏开始后,按照顺时针顺序,从编号为1的人开始依次取石子。对于留有i个石子的局面,被允许的取石子个数有a[i]种,取得最后一个石子的人获得胜利。

K个人将会遵循如下的策略:

l  如果有一些取石子的方法,能够保证无论别人按照什么策略游戏,都能确保自己获得胜利,那他会在这些方法中随机地选择一种,作为自己的决策。

l  否则,假定别人和自己采取同样的策略,如果有一些取石方法,能够使自己有可能获胜,他会在这些方法中随机地选择一种,作为自己的决策。

l  否则,他会随机地选择一种方法,作为自己的决策。

如果在某一轮,石子没有取完,同时没有任何被允许的取石方案,则认为没有人获得胜利。

现在请你求出最终哪些人可能获得胜利。

Input

输入第一行包含一个正整数n,表示桌上石子个数。

输入第二行包含一个正整数K

接下来n行,第i行的第一个整数为a[i],接下来a[i]个整数,表示还剩i个石子时,被允许的取石方案。

Output

从小到大输出一行正整数,即所有可能获得胜利的人的编号。如果没有人能获得胜利,则输出-1

Example1

NimForK.in

8

2

1 1

2 1 2

3 1 2 3

3 1 2 3

3 1 2 3

3 1 2 3

3 1 2 3

3 1 2 3

NimForK.out

2

Example2

NimForK.in

5

3

1 1

2 1 2

3 1 2 3

3 1 2 3

3 1 2 3

NimForK.out

2 3

Example3

NimForK.in

1

20

0

NimForK.out

-1

 

Constraints

对于30%的数据 n ≤ 10K ≤ 5

对于100%的数据 n ≤ 50K ≤ 20

 

...