Developing School's Contest 6
说明:此报告只是个人的总结,非官方报告。此中有些想法也是自己一孔之见,有不对的地方,望不吝赐教! 尚未完成,还在更新中··········
kuangbin
B.寻找最大值
Time Limit : 3000/1000ms (Java/Other) Memory Limit : 65535/32768K (Java/Other)
Total Submission(s) : 36 Accepted Submission(s) : 9
Font: Times New Roman | Verdana |Georgia
Font Size: ← →
Problem Description
我们都知道RMQ -(范围最小/最大查询),我们可以用它来解决这样的问题是找到最小值在一个区间,例如,1、2、3、4、2、4、6第1、8,如果你想知道最小值在[1—7],
您可以使用RMQ来解决它在O(1)时间。但是现在,我想知道另一件。我们选择一个区间,合计这个区间的总价值,并将这个总价值乘以该区间中的最小价值。现在我要让这个值最大。聪明的你应该知道怎么做吧?
Input
第一行输入包含n(1 < = n < = 100000),接着n个数字
Output
针对每种情况,输出定义内的最大值
Sample Input
6
3 1 6 4 5 2
4
1 100 100 1
Sample Output
60
20000
Author
syu
Source
Developing School's Contest 6
本题就是找一个区间,使得该区间的最小值乘以该区间所有数的总和。
本题要输出这个最大值。
思路很简单。由于输入的n个数都是非负的(虽然题目没有说)。如果确定了h[i]作为该区间的最小值,那么应该在保证h[i]为最小值的情况下让这个区间尽量大,这样就可以使得总和最小。
做法就是遍历一遍,让每一个数都成为最小值,取最大的区间。
比如样例
3 1 6 4 5 2
如果3作为最小值,那么区间只能取 3
如果1作为最小值,那么区间取 3 1 6 4 5 2
如果6作为最小值,那么区间取 6
如果4作为最小值,那么区间取 6 4 5
如果5作为最小值,那么区间取 5
如果2作为最小值,那么区间取 6 4 5 2
只要O(n)的复杂度就可以找出最大。
现在的问题是如果由最小值确定区间。
其实区间要尽量大,所以区间两边都是比最小值小的或者到了边界。
/* 1002 寻找最大值 G++ 468ms 2864k kuangbin */ #include<stdio.h> #include<iostream> #include<algorithm> using namespace std; const int MAXN=100010; long long h[MAXN];//数据必须用long long,int不行,数据较大 int L[MAXN];//L[i]表示L[i]-i的数都不会小于h[i],也就是L[i]-1是左侧第一个小于h[i]的数 int R[MAXN];//R[i]表示i-R[i]的数都不会小于h[i],也就是R[i]+1是右侧第一个小于h[i]的数 long long sum[MAXN];//前n项和 int main() { //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); int n; int i,j; while(scanf("%d",&n)!=EOF) { sum[0]=0; for(i=1;i<=n;i++) { scanf("%I64d",&h[i]); sum[i]=sum[i-1]+h[i]; } L[1]=1; for(i=2;i<=n;i++) { j=i; while(j>1&&h[j-1]>=h[i])//求a[i]左边不小于a[i]的位置 j=L[j-1]; L[i]=j; } R[n]=n; for(i=n-1;i>=1;i--) { j=i; while(j<n&&h[j+1]>=h[i]) j=R[j+1]; R[i]=j; } long long Max=-100000000; long long ans; for(i=1;i<=n;i++) { ans=h[i]*(sum[R[i]]-sum[L[i]-1]); if(Max<ans)Max=ans; } printf("%I64d\n",Max); } return 0; }
C.时间挑战
Time Limit : 3000/1000ms (Java/Other) Memory Limit : 65535/32768K (Java/Other)
Total Submission(s) : 70 Accepted Submission(s) : 16
Font: Times New Roman | Verdana |Georgia
Font Size: ← →
Problem Description
今天我们将接受一场关于时间的挑战,游戏规则如下:
给出N(1 < = N < = 200000)段时间,每段时间表示为[A,B],A为起始时间,B为终止时间。
对于两个时间段s和t,我们说s被t包括, At <= As 而且 Bs <= Bt。
请注意:如果At==As 并且 Bt==Bs的话,我们不认为s被t包括。
那么在所有N段时间中,对于每个时间段,你能告诉我他被多少时间段包括了么?
Input
输入包含多个测试用例。为每个测试用例中,第一行是一个整数N(1 < = N < = 200000)。
然后再N行,每行包含两个整数:Ai和Bi(Ai,Bi将不超过32位的无符号整数)。Ai、Bi如上述题意描述。
Output
对于每个测试样例,只需输出一行,该行包括n个整数,第i个数代表了(Ai,Bi)被多少时间段包括。
Sample Input
2
8467 14802
6500 15670
5
3 7
2 7
0 1
1 4
1 3
Sample Output
1 0
1 0 0 0 1
Author
syu
Source
Developing School's Contest 6
树状数组。
需要离散化。
参考POJ 2481
http://www.cnblogs.com/kuangbin/archive/2012/08/09/2630422.html
上面这个不需要离散化
按照右端点排序,再按照左端点排序
树状数组的应用,好好领悟。
/* 1003 G++ 765ms 6784K */ #include<stdio.h> #include<iostream> #include<algorithm> #include<string.h> #include<stdlib.h> using namespace std; const int MAXN=200020; struct Node { unsigned int x,y; int index; int i; }node[MAXN]; bool cmp(Node a,Node b)//先按y从大到小排序,再按照x从小到大 { if(a.y!=b.y)return a.y>b.y; return a.x<b.x; } bool cmp2(Node a,Node b)//先按x从小到大排序,再按照y从大到小 { if(a.x!=b.x)return a.x<b.x; return a.y>b.y; } int n; int b[MAXN]; int c[MAXN]; int lowbit(int x) { return x&(-x); } void add(int i,int val) { while(i<=n) { c[i]+=val; i+=lowbit(i); } } int sum(int i) { int s=0; while(i>0) { s+=c[i]; i-=lowbit(i); } return s; } int ans[MAXN]; int a[MAXN]; int main() { //freopen("in.txt","r",stdin); // freopen("out.txt","w",stdout); while(scanf("%d",&n)!=EOF) { for(int i=1;i<=n;i++) { scanf("%d%d",&node[i].x,&node[i].y); node[i].i=i; } sort(node+1,node+1+n,cmp);//排序 for(int i=1;i<=n;i++){node[i].index=i;a[i]=node[i].i;} sort(node+1,node+n+1,cmp2);//为了离散化排序 int t1; for(int i=1;i<=n;i++) { t1=node[i].index; if(i>1&&node[i].x==node[i-1].x&&node[i].y==node[i-1].y) b[t1]=b[node[i-1].index]; else b[t1]=i; } memset(c,0,sizeof(c)); // sort(node+1,node+1+n,cmp);//重新回到原来的顺序 for(int i=1;i<=n;i++) { add(b[i],1); ans[a[i]]=sum(b[i]-1); } for(int i=1;i<n;i++)printf("%d ",ans[i]); printf("%d\n",ans[n]); } return 0; }
下面的用的快速排序qsort,好像会快点
#include<stdio.h> #include<iostream> #include<algorithm> #include<string.h> #include<stdlib.h> using namespace std; const int MAXN=200020; struct Node { unsigned int x,y; int index; int i; }node[MAXN]; /* bool cmp(Node a,Node b) { if(a.y!=b.y)return a.y>b.y; return a.x<b.x; } bool cmp2(Node a,Node b) { if(a.x!=b.x)return a.x<b.x; return a.y>b.y; } */ int cmp(const void *a,const void *b) { struct Node *c=(Node *)a; struct Node *d=(Node *)b; if(c->y!=d->y)return d->y - c->y; else return c->x-d->x; } int cmp1(const void *a,const void *b) { struct Node *c=(Node *)a; struct Node *d=(Node *)b; if(c->x!=d->x)return c->x-d->x; else return d->y - c->y; } int n; int b[MAXN]; int c[MAXN]; int lowbit(int x) { return x&(-x); } void add(int i,int val) { while(i<=n) { c[i]+=val; i+=lowbit(i); } } int sum(int i) { int s=0; while(i>0) { s+=c[i]; i-=lowbit(i); } return s; } int ans[MAXN]; int a[MAXN]; int main() { //freopen("in.txt","r",stdin); // freopen("out.txt","w",stdout); while(scanf("%d",&n)!=EOF) { for(int i=1;i<=n;i++) { scanf("%d%d",&node[i].x,&node[i].y); node[i].i=i; } // sort(node+1,node+1+n,cmp); qsort(node+1,n,sizeof(node[0]),cmp); for(int i=1;i<=n;i++){node[i].index=i;a[i]=node[i].i;} // sort(node+1,node+n+1,cmp2); qsort(node+1,n,sizeof(node[0]),cmp1); int t1; for(int i=1;i<=n;i++) { t1=node[i].index; if(i>1&&node[i].x==node[i-1].x&&node[i].y==node[i-1].y) b[t1]=b[node[i-1].index]; else b[t1]=i; // printf("%d %d %d\n",node[i].index,node[i].x,node[i].y); } // for(int i=1;i<=n;i++)printf("%d ",b[i]); // printf("\n"); memset(c,0,sizeof(c)); // sort(node+1,node+1+n,cmp); for(int i=1;i<=n;i++) { add(b[i],1); ans[a[i]]=sum(b[i]-1); } for(int i=1;i<n;i++)printf("%d ",ans[i]); printf("%d\n",ans[n]); } return 0; }
J.Three Cards
Time Limit : 3000/1000ms (Java/Other) Memory Limit : 65535/32768K (Java/Other)
Total Submission(s) : 9 Accepted Submission(s) : 4
Font: Times New Roman | Verdana |Georgia
Font Size: ← →
Problem Description
LaoPei and A q are good friends with Debugcool and they like playing cards.There is a way to play cards called Three cards, it is to say, all of the players will get three cards and only one will be the winner.
As everyone knows, each card has one of four suits and one of thirteen values:
suits:clubs( C ),diamonds( D ),hearts( H )and spades( S ). They have no order.
values:2 < 3 < 4 < …… < 9 < T( 10 ) < J < Q < K < A .
And there will be seven types of the three cards on the players' hands:
1) BaoZi:the three cards have the same values, for example:AH AS AD, 2C 2D 2S
2) TongHuaShun:the three cards have the same suit and their values increase by one, for example:7C 8C 9C, JH QH KH
3) JinHua:the three cards have the same suit
4) ShunZi:the three cards' values increase by one
5) DuiZi:there are two cards in the three cards have the same values
6) Other:the other situation except the above
The order:Baozi > TongHuaShun > JinHua > ShunZi > DuiZi > Other, if the players' cards have the same type, the values will be taken into count:on one hand, if the same type is DuiZi, the value of the two cards who have the same value will be compared firstly, if they have the same value, the other card's value will be compared. On the other hand, if the type is not DuiZi, from the biggest to the smallest will be compared successively, eg. QC 10C 9C < KC 4C 3C. If all value of the three cards of the players are the same, they tied. eg. QC 10C 9C = QH 10H 9H.
Input
The input contains several test cases, each test case will have only one line to represent the cards in LaoPei's hand and A q's hand, every line will have six cards, three for LaoPei and three for A q. Each card will consist of two parts:the values and the suits. For example:AS mean spades with value A. The cards will be separated by a space.
Output
For each test case, output a line containing the result of the game. If LaoPei's cards is bigger than A q's, output "LaoPei wins!", if A q's cards is bigger than LaoPei's, output "A q wins!", if they tied, output "Oh my god, who wins, Debugcool knows!"
Sample Input
AC AD AH KC KD KH
TD QD JD QC KC JC
2D 2C 5S 2S 2H 5C
Sample Output
LaoPei wins!
A q wins!
Oh my god, who wins, Debugcool knows!
Author
syu
Source
Developing School's Contest 6
很简单的水题,就是麻烦点。要细心。
细节决定成败!
脑残地竟然以为J Q K是相邻的字母,得到数值的时候懒了一点,导致WR到死啊!
#include<stdio.h> #include<algorithm> #include<iostream> using namespace std; int getv(char c) { if(c>='2'&&c<='9')return c-'1'-1; else if(c=='A') return 13-1; else if(c=='T') return 9-1; else if(c=='J')return 10-1; else if(c=='Q') return 11-1; else if(c=='K') return 12-1; } int a[3]; int main() { //freopen("in.txt","r",stdin); // freopen("out.txt","w",stdout); int k1,k2;//种类 int t11,t12,t13,t21,t22,t23; char str1[10],str2[10],str3[10]; char str4[10],str5[10],str6[10]; while(scanf("%s%s%s%s%s%s",&str1,&str2,&str3,&str4,&str5,&str6)!=EOF) { a[0]=getv(str1[0]); a[1]=getv(str2[0]); a[2]=getv(str3[0]); sort(a,a+3); // printf("%d %d %d\n",a[0],a[1],a[2]); if(a[0]==a[1]&&a[1]==a[2]) { k1=1; t11=a[0]; } else if(str1[1]==str2[1]&&str1[1]==str3[1]) { if(a[1]==(a[0]+1)&&a[2]==(a[1]+1)) { k1=2; t11=a[2]; } else { k1=3; t11=a[2]; t12=a[1]; t13=a[0]; } } else if(a[1]==(a[0]+1)&&a[2]==(a[1]+1)) { k1=4; t11=a[2]; } else if((a[1]==a[0]&&a[1]!=a[2])||(a[0]!=a[1]&&a[1]==a[2])) { k1=5; if(a[1]==a[0]) { t11=a[1]; t12=a[2]; } else { t11=a[2]; t12=a[0]; } } else { k1=6; t11=a[2]; t12=a[1]; t13=a[0]; } a[0]=getv(str4[0]); a[1]=getv(str5[0]); a[2]=getv(str6[0]); sort(a,a+3); // printf("%d %d %d\n",a[0],a[1],a[2]); if(str4[0]==str5[0]&&str5[0]==str6[0]) { k2=1; t21=a[0]; } else if(str4[1]==str5[1]&&str5[1]==str6[1]) { if(a[1]==(a[0]+1)&&a[2]==(a[1]+1)) { k2=2; t21=a[2]; } else { k2=3; t21=a[2]; t22=a[1]; t23=a[0]; } } else if(a[1]==(a[0]+1)&&a[2]==(a[1]+1)) { k2=4; t21=a[2]; } else if((a[1]==a[0]&&a[1]!=a[2])||(a[0]!=a[1]&&a[1]==a[2])) { k2=5; if(a[1]==a[0]) { t21=a[1]; t22=a[2]; } else { t21=a[2]; t22=a[0]; } } else { k2=6; t21=a[2]; t22=a[1]; t23=a[0]; } // printf("%d %d\n",k1,k2); if(k1<k2) printf("LaoPei wins!\n"); else if(k1>k2) printf("A q wins!\n"); else { if(k1==1) { if(t11<t21)printf("A q wins!\n"); else if(t11>t21) printf("LaoPei wins!\n"); else printf("Oh my god, who wins, Debugcool knows!\n"); } else if(k1==2) { if(t11<t21)printf("A q wins!\n"); else if(t11>t21) printf("LaoPei wins!\n"); else printf("Oh my god, who wins, Debugcool knows!\n"); } else if(k1==3) { if(t11<t21)printf("A q wins!\n"); else if(t11>t21) printf("LaoPei wins!\n"); else { if(t12<t22)printf("A q wins!\n"); else if(t12>t22) printf("LaoPei wins!\n"); else { if(t13<t23)printf("A q wins!\n"); else if(t13>t23) printf("LaoPei wins!\n"); else printf("Oh my god, who wins, Debugcool knows!\n"); } } } else if(k1==4) { if(t11<t21)printf("A q wins!\n"); else if(t11>t21) printf("LaoPei wins!\n"); else printf("Oh my god, who wins, Debugcool knows!\n"); } else if(k1==5) { if(t11<t21)printf("A q wins!\n"); else if(t11>t21) printf("LaoPei wins!\n"); else { if(t12<t22)printf("A q wins!\n"); else if(t12>t22) printf("LaoPei wins!\n"); else printf("Oh my god, who wins, Debugcool knows!\n"); } } else if(k1==6) { if(t11<t21)printf("A q wins!\n"); else if(t11>t21) printf("LaoPei wins!\n"); else { if(t12<t22)printf("A q wins!\n"); else if(t12>t22) printf("LaoPei wins!\n"); else { if(t13<t23)printf("A q wins!\n"); else if(t13>t23) printf("LaoPei wins!\n"); else printf("Oh my god, who wins, Debugcool knows!\n"); } } } } } return 0; }
E.Container
Time Limit : 3000/1000ms (Java/Other) Memory Limit : 65535/32768K (Java/Other)
Total Submission(s) : 37 Accepted Submission(s) : 20
Font: Times New Roman | Verdana |Georgia
Font Size: ← →
Problem Description
Design a container, which has two kinds of operation, push and pop.
Push: You should push the given number into the container.
Pop: Please find the middle number of the container. If these is n numbers in container, it will be the (n+1)/2-th num when sort increased. Then pop the number.
Input
The input contains one or more data sets. At first line of each input data set is an integer N (1<= N <= 100000) indicate the number of operations.
Then N lines follows, each line contains a number (0 or 1). "0" means a push operation, it's followed by an integer E. "1" means a pop operation.
You may assume all the numbers in the input file will be in the range of 32-bit integer.
Output
For each pop operation, you should print the integer popped. Please print "No Element!", if there is no number to pop. Please print a blank line after each data set.
Sample Input
9
0 10
0 -10
0 5
1
1
0 2
1
1
1
3
0 2
0 1
1
Sample Output
5
-10
2
10
No Element!
1
Author
syu
Source
Developing School's Contest 6
这题很简单。
直接数组模拟竟然可以AC。。。。数据比较弱吧。囧了。。。
其实STL的排序函数什么的是比较慢的,远远没有自己开数组排序快。
最好的办法是建立两个优先队列。
/* 1005 G++ 105ms 768K */ #include<stdio.h> #include<queue> #include<algorithm> #include<iostream> using namespace std; priority_queue<int>q1;//默认的是大的优先级高的,大的先出队的优先队列 struct cmp { bool operator()(int x,int y) { return x>y;//x小的优先级高 } }; priority_queue<int,vector<int>,cmp>q2; //小的优先级高的,小的先出队的优先队列 int main() { //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); int n; int A,B; int num;//数的数量 while(scanf("%d",&n)!=EOF) { while(!q1.empty())q1.pop(); while(!q2.empty())q2.pop(); //q1存放前(num+1)/2个数 //q2存放后面的(num-1)/2个数; //也就是q1和q2里面数的个数要么相等,要么q1比q2多1; //否则就需要调整 num=0; while(n--) { scanf("%d",&A); if(A==0) { scanf("%d",&B); if(num==0) { num++; q1.push(B); } else { num++; if(B<=q1.top()) { q1.push(B); if(q1.size()-q2.size()>1) { q2.push(q1.top()); q1.pop(); } } else { q2.push(B); if(q2.size()>q1.size()) { q1.push(q2.top()); q2.pop(); } } } } else { if(num==0)printf("No Element!\n"); else { num--; printf("%d\n",q1.top()); q1.pop(); if(q1.size()<q2.size()) { q1.push(q2.top()); q2.pop(); } } } } printf("\n"); } return 0; }
另外附上AC的水程序:
/* 1005 G++ 625ms 388K */ #include<stdio.h> #include<algorithm> using namespace std; const int MAXN=1000100; int que[MAXN]; int main() { int top,n,a,b,i; while(scanf("%d",&n)!=EOF) { top=1; while(n--) { scanf("%d",&a); if(a==0) { scanf("%d",&b); for(i=top;i>1;i--) { if(que[i-1]<=b)break; else que[i]=que[i-1]; } que[i]=b; top++; } else { if(top<=1)printf("No Element!\n"); else { int temp=top/2; printf("%d\n",que[temp]); for(int i=temp;i<top-1;i++) que[i]=que[i+1]; top--; } } } printf("\n"); } return 0; }
G.K阶整数对
Time Limit : 3000/1000ms (Java/Other) Memory Limit : 65535/32768K (Java/Other)
Total Submission(s) : 5 Accepted Submission(s) : 5
Font: Times New Roman | Verdana |Georgia
Font Size: ← →
Problem Description
设一个有序整数对(n,m)满足如下关系:
1) (n2-m*n-m2)2=1
2) n>=m
3) n>=1,m>=1
现将所有满足条件的(n,m)升序排列,问第K个序列是多少?
Input
每个测试用例包含单个整数k(1 < = k < = 109)。输入k = 0时终止。
Output
为每个测试用例,输出一行m和n的值在 mod 2009后。两个整数用空格分隔。
Sample Input
4
20
0
Sample Output
3 5
738 901
Author
syu
Source
Developing School's Contest 6
n2-mn-m2 = -(m2+mn-n2)
= -[(m+n)2-mn-2n2]
= -[(m+n)2- n(m+n) -n2]
(n,m)->((m+n),n)
(1,1)满足条件,即为第一组
(1,1)->(2,1)->(3,2)......
第k对即为斐波那契数的第k+1个和第k个
矩阵乘法求出第k个斐波那契数即可。
/* 1007 G++ 15ms 220KB kuangbin */ #include<stdio.h> #include<math.h> int m=2009; int A[2][2]; int B[2][2]={0,1,1,1}; int C[2][2]; void mul(int a[][2],int b[][2],int c[][2]) {//功能,求出a*b存在c里 int i,j,h; for(i=0;i<2;i++) for(j=0;j<2;j++) { c[i][j]=0; for(h=0;h<2;h++) c[i][j]+=a[i][h]*b[h][j]; c[i][j]%=m; } } void qiu(int x,int a[][2])//求出 B 的x次方,存在a里 { int i,j; int b[2][2]; if(x==1) //x等于1时,直接把B存在a里 { for(i=0;i<2;i++) for(j=0;j<2;j++) a[i][j]=B[i][j]; return; } if(x%2==0) { qiu(x/2,b); mul(b,b,a); } else { qiu(x-1,b); mul(b,B,a); } } int main() { int c[2][2]; int k; while(scanf("%d",&k),k) { if(k==1){printf("1 1\n");continue;} if(k==2){printf("1 2\n");continue;} A[0][0]=1;A[0][1]=1;//A={a1,a2} A[1][0]=0;A[1][1]=0; qiu(k-1, C); mul(A,C,c); printf("%d %d\n",c[0][0]%m,c[0][1]%m); } return 0; }
K.Teamwork Brings Profits!
Time Limit : 3000/1000ms (Java/Other) Memory Limit : 65535/32768K (Java/Other)
Total Submission(s) : 9 Accepted Submission(s) : 8
Font: Times New Roman | Verdana |Georgia
Font Size: ← →
Problem Description
Williammed's father is running a small company now, which has N employees.(2<=N<=10 and N is an even number). The employees are numbered from 1 to N. All the employees are divided into N/2 groups. One employee can only be in one group, and each group works on one project. As we all know, teamwork is very important to a company, so different team can make different profits. And now, given any two people i and j, Williammed's father can tell how much profit(Pij) can they make if they work together. Here comes the problem, given all the Pij(1 <= i <= N,1 <= j <= N,0 < Pij<= 100), you should tell the most profits this company can make. This is an easy problem, isn't it?
Input
The first line of the input is N(2<=N<=10 and N is an even number),the number of employees in the company.
Then there're N lines,each line has N numbers.The jth number in the ith line is Pij,as we discribe above.And we guarantee Pij = Pji,Pii = 0.
The end-of-file is denoted by a single line containing the integer 0.
Output
For each case,output the most profits this company can make.
Sample Input
4
0 6 62 13
6 0 35 94
62 35 0 5
13 94 5 0
0
Sample Output
156
Author
syu
Source
Developing School's Contest 6
简单搜索,不解释。
/* 1011 搜索 G++ 93ms 488K kuangbin */ #include<stdio.h> #include<string.h> #include<iostream> using namespace std; const int MAXN=20; int n; bool used[MAXN]; int ans; int P[MAXN][MAXN]; void dfs(int pair,int t) { if(pair==n/2) { if(t>ans)ans=t; return; } for(int i=0;i<n;i++) { if(!used[i]) { for(int j=i+1;j<n;j++) { if(!used[j]) { used[i]=used[j]=true; dfs(pair+1,t+P[i][j]); used[i]=used[j]=false; } } } } } int main() { while(scanf("%d",&n),n) { for(int i=0;i<n;i++) for(int j=0;j<n;j++) scanf("%d",&P[i][j]); memset(used,false,sizeof(used)); ans=-1; dfs(0,0); printf("%d\n",ans); } return 0; }
A.Chess
Time Limit : 3000/1000ms (Java/Other) Memory Limit : 65535/32768K (Java/Other)
Total Submission(s) : 9 Accepted Submission(s) : 3
Font: Times New Roman | Verdana |Georgia
Font Size: ← →
Problem Description
We have a chessboard, as the figure below, it shows the chessboard with dimension 1, 3, 5, 7 (We ignore the even number).Now, your task is to place K bishops on the n – dimension chessboard and satisfied that none of then attack each other ( A bishop can move to any distance in any of the four diagonal directions).
Input
输入包含两个整数n(n < 100 & & n % 2 = = 1)和k(k < = 10000)之间用一个空格分开。
Output
输出的答案mod 100007.
Sample Input
7 3
1 1
Sample Output
1038
1
Author
syu
Source
Developing School's Contest 6
题目的意思比较难懂。
其实如上图所示。
要在N维的上述图形中放k个物体。
图中画的对角线是冲突的。
也就是每条对角线上最多只能有一个物体。
很容易看得出红色和黄色是不冲突的。
可以看成独立的。
这个问题就分成了两个图形,相当于在方格中放车的问题了。
很容易推出公式。
公式在程序注释中写了。
/* 1001 如果要在 n*n 的方格中放k个东西,零每个东西不能在同一行或者同一列 显然最多可以放n个。 放的时候肯定是每个东西占用独有的一行和一列 首先选好行 ,有C(n,k)种选择。 选择好k行之后就给这k行选列。 第1个行有n个选择,第2个有n-1个选择•••••第k行有n-k+1个选择。 即选择数为P(n,k);//有人习惯写 A(n,k) 那么可以得到 a[n][k]=C[n][k]*P[n][k]; 题目中输入n,相当于有了两个方格,(n/2)*(n/2)的方格,(n/2+1)*(n/2+1)的方格。 在这两种方格中放总共k个的总数。 那只要循环一次就可以求出来了。 打表实现。 G++ 15ms */ #include<stdio.h> const int MAXN=100; const int MOD=100007; int C[MAXN][MAXN];//组合数 int P[MAXN][MAXN];//排列数 long long a[MAXN][MAXN];//a[i][j]表示i*i的方格中放j个的种数 //a[n][k]=C[n][k]*P[n][k] long long ans[MAXN][MAXN]; void init() { C[0][0]=1; C[1][0]=1; C[1][1]=1; for(int i=2;i<MAXN;i++) { C[i][0]=1; C[i][i]=1; for(int j=1;j<i;j++) C[i][j]=(C[i-1][j]+C[i-1][j-1])%MOD;//组合数基本性质公式 } P[0][0]=1; for(int i=1;i<MAXN;i++) { P[i][0]=1; for(int j=1;j<=i;j++) { P[i][j]=P[i][j-1]*(i-j+1); P[i][j]%=MOD; } } a[0][0]=1; for(int i=1;i<MAXN;i++) { for(int j=0;j<=i;j++) { a[i][j]=(long long)C[i][j]*P[i][j]; a[i][j]%=MOD; } } for(int i=1;i<MAXN;i+=2) { for(int j=1;j<=i;j++) { ans[i][j]=0; for(int k=0;k<=i/2;k++) { ans[i][j]+=a[i/2][k]*a[i/2+1][j-k]; ans[i][j]%=MOD; } } } } int main() { // freopen("in.txt","r",stdin); // freopen("out.txt","w",stdout); int n,k; init(); while(scanf("%d%d",&n,&k)!=EOF) { if(k>n)printf("0\n"); else if(k==0) printf("1\n");//? else printf("%I64d\n",ans[n][k]); } }
等待更新中······