UVALive - 6916 Punching Robot Lucas+dp
2016-09-03 01:02
399 查看
题目链接:
http://acm.hust.edu.cn/vjudge/problem/96344Punching Robot
Time Limit: 1000MS64bit IO Format: %lld & %llu题意
在n*m的棋盘上有k个障碍物,并且这k个障碍物周围8个格子也都是障碍物,问从(1,1)到(n,m)总共有多少种不经过障碍物任何的走法(每次只能向下走或者向右走。
题解
这题和之前的一道题基本相同:点这里
由于给的质数比较小,所以不能保证互质(比如说mod与mod就不会互质了),所以求逆的时候会出问题,可以考虑求阶乘的时候单独把997这个因子全部提出来,并且记录下个数,单独讨论一下就可以做了。
#include<map> #include<set> #include<cmath> #include<queue> #include<stack> #include<ctime> #include<vector> #include<cstdio> #include<string> #include<bitset> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #include<functional> using namespace std; #define X first #define Y second #define mkp make_pair #define lson (o<<1) #define rson ((o<<1)|1) #define mid (l+(r-l)/2) #define sz() size() #define pb(v) push_back(v) #define all(o) (o).begin(),(o).end() #define clr(a,v) memset(a,v,sizeof(a)) #define bug(a) cout<<#a<<" = "<<a<<endl #define rep(i,a,b) for(int i=a;i<(b);i++) #define scf scanf #define prf printf typedef long long LL; typedef vector<int> VI; typedef pair<int,int> PII; typedef vector<pair<int,int> > VPII; const int INF=0x3f3f3f3f; const LL INFL=0x3f3f3f3f3f3f3f3fLL; const double eps=1e-8; const double PI = acos(-1.0); //start---------------------------------------------------------------------- const int maxn=2e6+10; const int mod=997; int n,m,k; LL dp[111],fac[maxn]; int num[maxn]; VPII robot; void gcd(LL a,LL b,LL& d,LL& x,LL& y){ if(!b){ d=a; x=1; y=0; } else{ gcd(b,a%b,d,y,x); y-=x*(a/b); } } LL Inv(LL a,int mod){ LL d,x,y; gcd(a,mod,d,x,y); return d==1?(x+mod)%mod:-1; } LL get_C(int n,int m){ if(n<m||n<0||m<0) return 0; if(num !=num[m]+num[n-m]) return 0; return fac *Inv(fac[m]*fac[n-m]%mod,mod)%mod; } LL calc(int i,int j){ int n=robot[j].X-robot[i].X; int m=robot[j].Y-robot[i].Y; if(n<0||m<0) return 0; return get_C(n+m,n); } void pre(){ clr(num,0); fac[0]=1; for(int i=1;i<maxn;i++){ int x=i; num[i]+=num[i-1]; while(x%mod==0){ x/=mod; num[i]++; } fac[i]=fac[i-1]*x%mod; } } void init(){ clr(dp,0); robot.clear(); } int main() { pre(); int tc,kase=0; scf("%d",&tc); while(tc--){ scf("%d%d%d",&n,&m,&k); init(); int su=1; for(int i=1;i<=k;i++){ int x,y; scf("%d%d",&x,&y); for(int dx=-1;dx<=1;dx++){ for(int dy=-1;dy<=1;dy++){ int a=x+dx,b=y+dy; robot.pb(mkp(a,b)); if(a==1&&b==1||a==n&&b==m){ su=0; } } } } if(!su){ puts("0"); continue; } robot.pb(mkp(1,1)); robot.pb(mkp(n,m)); sort(robot.begin(),robot.end()); for(int i=1;i<robot.sz();i++){ dp[i]=calc(0,i); for(int j=1;j<i;j++){ dp[i]=(dp[i]-dp[j]*calc(j,i)%mod)%mod; } dp[i]=(dp[i]+mod)%mod; } printf("Case #%d: %lld\n",++kase,dp[robot.sz()-1]); } return 0; } //end-----------------------------------------------------------------------
其实直接上卢卡斯就不会有不互质的困扰啦!(跑的更快!)
#include<map> #include<set> #include<cmath> #include<queue> #include<stack> #include<ctime> #include<vector> #include<cstdio> #include<string> #include<bitset> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #include<functional> using namespace std; #define X first #define Y second #define mkp make_pair #define lson (o<<1) #define rson ((o<<1)|1) #define mid (l+(r-l)/2) #define sz() size() #define pb(v) push_back(v) #define all(o) (o).begin(),(o).end() #define clr(a,v) memset(a,v,sizeof(a)) #define bug(a) cout<<#a<<" = "<<a<<endl #define rep(i,a,b) for(int i=a;i<(b);i++) #define scf scanf #define prf printf typedef long long LL; typedef vector<int> VI; typedef pair<int,int> PII; typedef vector<pair<int,int> > VPII; const int INF=0x3f3f3f3f; const LL INFL=0x3f3f3f3f3f3f3f3fLL; const double eps=1e-8; const double PI = acos(-1.0); //start---------------------------------------------------------------------- const int maxn=2e6+10; const int mod=997; int n,m,k; LL dp[111],fac[mod+10],facinv[mod+10],inv[mod+10]; VPII robot; LL get_C(int n,int m){ if(n<m||n<0||m<0) return 0; return fac *facinv[n-m]%mod*facinv[m]%mod; } LL Lucas(LL n,LL m,LL p){ if(m==0) return 1LL; return get_C(n%p,m%p)*Lucas(n/p,m/p,p)%p; } LL calc(int i,int j){ int n=robot[j].X-robot[i].X; int m=robot[j].Y-robot[i].Y; if(n<0||m<0) return 0; return Lucas(n+m,n,mod); } void pre(){ fac[0]=fac[1]=1; facinv[0]=facinv[1]=1,inv[1]=1; for(int i=2;i<mod;i++){ fac[i]=fac[i-1]*i%mod; inv[i]=(mod-mod/i)*inv[mod%i]%mod; facinv[i]=facinv[i-1]*inv[i]%mod; } } void init(){ clr(dp,0); robot.clear(); } int main() { pre(); int tc,kase=0; scf("%d",&tc); while(tc--){ scf("%d%d%d",&n,&m,&k); init(); int su=1; for(int i=1;i<=k;i++){ int x,y; scf("%d%d",&x,&y); for(int dx=-1;dx<=1;dx++){ for(int dy=-1;dy<=1;dy++){ int a=x+dx,b=y+dy; robot.pb(mkp(a,b)); if(a==1&&b==1||a==n&&b==m){ su=0; } } } } if(!su){ puts("0"); continue; } robot.pb(mkp(1,1)); robot.pb(mkp(n,m)); sort(robot.begin(),robot.end()); for(int i=1;i<robot.sz();i++){ dp[i]=calc(0,i); for(int j=1;j<i;j++){ dp[i]=(dp[i]-dp[j]*calc(j,i)%mod)%mod; } dp[i]=(dp[i]+mod)%mod; } printf("Case #%d: %lld\n",++kase,dp[robot.sz()-1]); } return 0; } //end-----------------------------------------------------------------------
相关文章推荐
- UVALive 6916---Punching Robot(卢卡斯+容斥)
- Maze For Robot - UVaLive 4040 dp
- UVALive 6916 Punching Robot dp
- UVALive 6908---Electric Bike(DP或记录型深搜)
- UVaLive 3490 - Generator (AC自动机 期望DP 高斯消元)
- UVALive6257-剪枝|dp-Chemist's vows
- UVAlive 2031 - Dance Dance Revolution(dp,黑书dp例四)
- DP(优化) UVALive 6073 Math Magic
- Cross the Wall UVALive - 5097 (贪心+斜率dp)
- UVALive 6430 (水dp)
- UVALive 4987---Evacuation Plan(区间DP)
- UVALive 2038 Strategic game (树形DP,4级)
- UVALive 7392 Bundles of Joy【bitset】【类树形DP】【杂题】
- uvalive 6669 hidden tree(好壮压dp)
- Perfect Domination on Trees [UVALive 3346] 树形DP
- UVALive 4731 dp+贪心
- UVALive 4126 Password Suspects(AC自动机 套 DP)
- Uvalive 6434 - Number Assignment(dp)
- Uvalive 6259 Word equations dfs+dp
- uva live 6190 Beautiful Spacing (二分+dp检验 根据特有性质优化)