zoukankan      html  css  js  c++  java
  • 【BZOJ】2172: Mario填格子

    题意

    (3 * 3)的网格,给出左上角的数字(m)和右下角的数字(m),如果当前格子有数字(x),格子左边有个数字(y),格子上面有个数字(z),则(y|x, z|x)。格子中不存在相同的两个数。问是否存在填满格子的方案。

    分析

    最优放法肯定是每一个格子放的数相是上面和左边的数的最小公倍数或乘上了一个质因子。
    首先我们质因子肯定是(p=m/n)的质因子(如果(m \% n eq 0)则显然无解)而且可以把左上角看成(1),右下角看成(p)
    (下面假设(a, b, c, d)(p)的质因子,且个数依次递增)
    如果(p)的质因子种类超过(3)种,则显然成立。

    $$ egin{matrix} 1 & a & ad \ b & ab & abd \ bc & abc & p \ end{matrix} $$

    如果(p)的质因子种类只有(3)种,(c)的个数要超过(1)

    $$ egin{matrix} 1 & c & cc \ b & bc & bcc \ ab & abc & p \ end{matrix} $$

    如果(p)的质因子种类只有(2)种,(a, b)的个数要超过(1)或者(b)的个数超过(4)种。

    $$ egin{matrix} 1 & a & aa \ b & ab & aab \ bb & abb & p \ end{matrix} $$

    $$ egin{matrix} 1 & a & ab \ b & abb & abbb \ bb & abbbb & p \ end{matrix} $$

    如果(p)的质因子种类只有(1)种,(a)的个数要超过(7)

    $$ egin{matrix} 1 & a & aa \ aaa & aaaa & aaaaaaa \ aaaaa & aaaaaa & p \ end{matrix} $$

    题解

    分解质因数用(Pollard-Rho),然后判断即可。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    ll rand(ll l, ll r) {
    	static ll mo=1e9+7, g=78125, now=199811;
    	return l+((now*=g)%=mo)%(r-l+1);
    }
    ll mul(ll a, ll b, ll mo) {
    	a%=mo;
    	ll x=0;
    	for(; b; b>>=1) {
    		if(b&1) {
    			x+=a;
    			if(x>=mo) {
    				x-=mo;
    			}
    		}
    		a<<=1;
    		if(a>=mo) {
    			a-=mo;
    		}
    	}
    	return x;
    }
    ll ipow(ll a, ll b, ll mo) {
    	ll x=1;
    	for(; b; b>>=1, a=mul(a, a, mo)) {
    		if(b&1) {
    			x=mul(x, a, mo);
    		}
    	}
    	return x;
    }
    bool check(ll n) {
    	if(n==2 || n==3 || n==5 || n==7 || n==11 || n==13 || n==17 || n==19) {
    		return 1;
    	}
    	if(n%2==0 || n%3==0 || n%5==0 || n%7==0 || n%11==0 || n%13==0 || n%17==0 || n%19==0) {
    		return 0;
    	}
    	ll d=n-1;
    	int cnt=0;
    	for(; !(d&1); d>>=1, ++cnt);
    	for(int tt=0; tt<15; ++tt) {
    		ll now=ipow(rand(2, n-1), d, n), pre=now;
    		for(int i=0; i<cnt; ++i) {
    			now=mul(now, now, n);
    			if(now==1 && pre!=1 && pre!=n-1) {
    				return 0;
    			}
    			pre=now;
    		}
    		if(now!=1) {
    			return 0;
    		}
    	}
    	return 1;
    }
    ll gcd(ll a, ll b) {
    	return b?gcd(b, a%b):a;
    }
    ll poi(ll n, ll c) {
    	for(int i=2; i<=20; ++i) {
    		if(n%i==0) {
    			return i;
    		}
    	}
    	ll x=rand(1, n-1), y=x, g;
    	for(int k=2, i=2; ; ++i) {
    		x=mul(x, x, n)+c;
    		if(x>=n) {
    			x-=n;
    		}
    		if((g=gcd(n, (y-x+n)%n))!=1) {
    			return g;
    		}
    		if(x==y) {
    			return n;
    		}
    		if(k==i) {
    			y=x;
    			k<<=1;
    		}
    	}
    }
    void po(ll n, ll f[], bool flag=1) {
    	if(n==1) {
    		return;
    	}
    	if(check(n)) {
    		if(flag) {
    			return;
    		}
    		f[++f[0]]=n;
    		return;
    	}
    	ll d;
    	while((d=poi(n, rand(1, n-1)))==n);
    	po(d, f, 0);
    	po(n/d, f, 0);
    }
    ll f[35], a[35], n, m;
    int num;
    int main() {
    	while(~scanf("%lld%lld", &n, &m)) {
    		if(m%n) {
    			puts("Wario_wins!
    ");
    			continue;
    		}
    		m/=n;
    		memset(f, 0, sizeof f);
    		num=0;
    		po(m, f);
    		if(f[0]) {
    			sort(f+1, f+1+f[0]);
    			a[num=1]=1;
    			for(int i=2; i<=f[0]; ++i) {
    				if(f[i]!=f[i-1]) {
    					a[++num]=1;
    				}
    				else {
    					a[num]++;
    				}
    			}
    			sort(a+1, a+1+num);
    		}
    		bool flag=num>=4 || (num==3&&a[num]>1) || (num==2&&((a[num]>1&&a[num-1]>1)||(a[num]>4))) || (num==1&&a[num]>7);
    		puts(flag?"Mario_wins!
    ":"Wario_wins!
    ");
    	}
    	return 0;
    }
  • 相关阅读:
    暑假第五周报告
    读《大道至简》有感
    暑假第四周报告
    暑假第三周报告
    暑假第二周报告
    暑假第一周报告
    对15号夏壹队的TD信息通——teamfinal的使用体验
    Django易混淆问题
    MySQL常见问题
    Django框架的理解和使用的常见问题
  • 原文地址:https://www.cnblogs.com/iwtwiioi/p/4985711.html
Copyright © 2011-2022 走看看