【bzoj4676】 两双手

http://www.lydsy.com/JudgeOnline/problem.php?id=4767 (题目链接)

题意

  求在网格图上从$(0,0)$走到$(n,m)$,其中不经过一些点的路径方案数。

Solution

  转换一下就变成了题意中的模型。我们将网格上的起点和不允许经过的点全部看做一类点,用$f[i]$表示从第$i$个点不经过其它点到达终点的路径条数,用$D(i,j)$表示个点之间的路径条数,$T$表示终点。转移:

\begin{aligned}  f[i]=D(i,T)-\sum_j D(i,j)*f[j]   \end{aligned}

  其中$j$在$i$的右上方。然后注意特判一下问题无法转换的情况。

细节

  预处理别预处理少了?

代码

// bzoj4767
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#define LL long long
#define inf (1ll<<30)
#define MOD 1000000007
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout)
using namespace std;

const int maxn=1000;
int Ex,Ey,Ax,Ay,Bx,By,na,nb,n,m;
LL fac[maxn*maxn],ifac[maxn*maxn],f[maxn];
struct point {
	int x,y;
	friend bool operator <= (point a,point b) {return a.x<=b.x && a.y<=b.y;}
}p[maxn];

LL power(LL a,LL b) {
	LL res=1;
	while (b) {
		if (b&1) (res*=a)%=MOD;
		b>>=1;(a*=a)%=MOD;
	}
	return res;
}
LL C(int n,int m) {
	return fac[n]*ifac[m]%MOD*ifac[n-m]%MOD;
}
bool cmp(point a,point b) {
	return a.x==b.x ? a.y<b.y : a.x<b.x;
}
LL D(point a,point b) {
	return C(b.x+b.y-a.x-a.y,b.x-a.x);
}
int main() {
	scanf("%d%d%d",&Ex,&Ey,&n);
	scanf("%d%d%d%d",&Ax,&Ay,&Bx,&By);
	if ((Ex*By-Ey*Bx)%(Ax*By-Ay*Bx)) {puts("0");return 0;}
	na=(Ex*By-Ey*Bx)/(Ax*By-Ay*Bx);
	nb=Bx ? (Ex-Ax*na)/Bx : (Ey-Ay*nb)/By;
	if (p[0].x<0 || p[0].y<0) {puts("0");return 0;}
	for (int ca,cb,x,y,i=1;i<=n;i++) {
		scanf("%d%d",&x,&y);
		if ((x*By-y*Bx)%(Ax*By-Ay*Bx)) continue;
		ca=(x*By-y*Bx)/(Ax*By-Ay*Bx);
		cb=Bx ? (x-Ax*ca)/Bx : (y-Ay*ca)/By;
		if (0<=ca && ca<=na && 0<=cb && cb<=nb) p[++m]=(point){ca,cb};
	}
	sort(p+1,p+1+m,cmp);
	n=na+nb;
	p[m+1]=(point){na,nb};p[0]=(point){0,0};
	fac[0]=1;for (int i=1;i<=n;i++) fac[i]=fac[i-1]*i%MOD;
	ifac[n]=power(fac[n],MOD-2);
	for (int i=n;i>=1;i--) ifac[i-1]=ifac[i]*i%MOD;
	for (int i=m;i>=0;i--) {
		f[i]=D(p[i],p[m+1]);
		for (int j=i+1;j<=m;j++) 
			if (p[i]<=p[j]) (f[i]+=MOD-D(p[i],p[j])*f[j]%MOD)%=MOD;
	}
	printf("%lld",f[0]);
	return 0;
}

 

转载于:https://www.cnblogs.com/MashiroSky/p/6532814.html

BZOJ 2908 题目是一个数据下载任务。这个任务要求下载指定的数据文件,并统计文件中小于等于给定整数的数字个数。 为了完成这个任务,首先需要选择一个合适的网址来下载文件。我们可以使用一个网络爬虫库,如Python中的Requests库,来帮助我们完成文件下载的操作。 首先,我们需要使用Requests库中的get()方法来访问目标网址,并将目标文件下载到我们的本地计算机中。可以使用以下代码实现文件下载: ```python import requests url = '目标文件的网址' response = requests.get(url) with open('本地保存文件的路径', 'wb') as file: file.write(response.content) ``` 下载完成后,我们可以使用Python内置的open()函数打开已下载的文件,并按行读取文件内容。可以使用以下代码实现文件内容读取: ```python count = 0 with open('本地保存文件的路径', 'r') as file: for line in file: # 在这里实现对每一行数据的判断 # 如果小于等于给定整数,count 加 1 # 否则,不进行任何操作 ``` 在每一行的处理过程中,我们可以使用split()方法将一行数据分割成多个字符串,并使用int()函数将其转换为整数。然后,我们可以将该整数与给定整数进行比较,以判断是否小于等于给定整数。 最后,我们可以将统计结果打印出来,以满足题目的要求。 综上所述,以上是关于解决 BZOJ 2908 数据下载任务的简要步骤和代码实现。 希望对您有所帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值