C. Gerald's Hexagon
题目大意:给定一个六边形,边长a1,a2,a3,a4,a5,a6,各内角是120°,且整数边长,求用平行边的线能分割成多少个边长为 1 的三角形;
思路:N边形一定是很规则的(由上条件,画图可知),见下图,整个补全,会是正三角形,分割数数(a1+a2+a3)^2,再减三个角多余的三个三角形(a1^2+a3^2+a5^2)
代码:http://codeforces.com/contest/560/submission/12191278
/* rush->AC */
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<string>
#include<queue>
#include<deque>
#include<stack>
#include<map>
#include<set>
#define INF 1<<29
#define mod 1000000007
//#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
int main()
{
int a[10];
for(int i=1;i<=5;i++)
{
scanf("%d",a+i);
}
int aa=a[1]+a[2]+a[3];
printf("%d\n",aa*aa-a[1]*a[1]-a[3]*a[3]-a[5]*a[5]);
return 0;
}
D. Equivalent Strings
题目大意:判断两个等长串是否相似;条件:
equal length are called equivalent in one of the two cases:
- They are equal.
- If we split string a into two halves of the same sizea1 and a2, and string b into two halves of the same size b1 andb2, then one of the following is correct:
- a1 is equivalent tob1, and a2 is equivalent to b2
- a1 is equivalent tob2, and a2 is equivalent to b1
代码:http://codeforces.com/contest/560/submission/12203505
/* rush->AC */
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<string>
#include<queue>
#include<deque>
#include<stack>
#include<map>
#include<set>
#define INF 1<<29
#define mod 1000000007
//#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
bool cmp(char *a,char *b,int len)
{
for(int i=0;i<len;i++)
if(a[i]!=b[i]) return false;
return true;
}
int dfs(char *a,char *b,int len)
{
if(cmp(a,b,len)) return 1;
if(len%2==1) return 0;
len/=2;
if(dfs(a,b,len)&&dfs(a+len,b+len,len)) return 1;
if(dfs(a,b+len,len)&&dfs(a+len,b,len)) return 1;
return 0;
}
char a[200001],b[200001];
int main()
{
cin>>a>>b;
int len=strlen(a);
if(dfs(a,b,len)) printf("YES\n");
else
printf("NO\n");
return 0;
}
E. Gerald and Giant Chess
题目大意:给一个h*w的棋盘,还有n个位于(r,c)的不可走黑点,求出 从右上(1,1)走到左下(h,w)有多少种方法;
思路:
结论:1> 从(1,1)走到(x,y),当没有黑点是,有C(x+y,x)方法;
2> 组合数去模 a / b % mod =a* ( b^(mod-2))%mod;
3> 对阶乘取模 inv[ i ]= inv [i+1]*(i+1)%mod;
又由于,这题有多个黑点,可分别求出sum[i],表示(1,1)到黑点i ( xi , yi )的方法数,如果它左上方有黑点 j (xj , yj ),sum[ i ] = C(xi+yi , xi) -C(xi-xj+yi-yj,xi-xj)*sum[ j ],
先对Point,黑点按x,y升序排列,然后递推;
代码:http://codeforces.com/contest/560/submission/12235227
/* SKY */
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
//#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll mod=1e9+7;
struct Point{
int x,y;
void set_(int x=0,int y=0){
this->x=x;
this->y=y;
}
bool operator <(const Point p) const{
return x<p.x||(x==p.x&&y<p.y);
}
}p[2007];
int inv[200007];
int fac[200007];
int sum[2007];
int h,w,n;
ll pow(ll a,ll b){
ll ret=1;
while(b){
if(b&1) ret=ret*a%mod;
b>>=1;
a=a*a%mod;
}
return ret%mod;
}
void init(){
fac[0]=inv[0]=1;
for(int i=1;i<=h+w;i++){
fac[i]=(ll)fac[i-1]*i%mod;
}
int c=max(h,w);
inv[c]=pow((ll)fac[c],mod-2);//cout<<inv[c]<<endl;
for(int i=c-1;i>0;i--){
inv[i]=(ll)inv[i+1]*(i+1)%mod;
}
}
int main(){
while(scanf("%d%d%d",&h,&w,&n)!=EOF){
init();
for(int i=0;i<n;i++){
scanf("%d%d",&p[i].x,&p[i].y);
}
p[n].set_(h,w);
sort(p,p+n+1);
for(int i=0;i<=n;i++){
sum[i]=(ll)fac[p[i].x-1+p[i].y-1]*inv[p[i].x-1]%mod*inv[p[i].y-1]%mod;
for(int j=0;j<i;j++)
if(p[i].x<=p[i].x&&p[j].y<=p[i].y){
int x_=p[i].x-p[j].x,y_=p[i].y-p[j].y;
sum[i]=(sum[i]-(ll)fac[x_+y_]*inv[x_]%mod*inv[y_]%mod*sum[j]%mod+mod)%mod;
}
}
printf("%d\n",sum[n]);
}
return 0;
}