zoukankan      html  css  js  c++  java
  • luogu P3403 跳楼机 同余最短路

    LINK:跳楼机

    很早之前就想学的一个东西。发现这个东西果然神奇。

    我们要找到 所有的 w满足 (w=1+ax+by+cz).且 (1leq wleq h)

    暴力枚举是不行的。

    做法是这样的:先考虑 ax+by的情况 考虑先让x和y组合成一堆数字 然后最后加上一些z。

    考虑对于一个楼层c 设res=c%z. 那么只要(ax+by)%z == res 找到这个最小的楼层那么之后所有 %z==res 的楼层都可以到达。

    那么对于更多的ax+by的组合我们也只需要靠z到达即可。

    考虑是否存在重复?不难发现因为同余的原因 每一个楼层最多只会在一个余数被计数。

    考虑最小的楼层可以记录之后所有的楼层。

    所以设(f_i)表示ax+by能跑到i层的最小楼层。

    可以简单的发现 对于一个余数i来说 对答案的贡献为 (frac{(h-f_i)}{z}+1)

    其主要利用了固定两个参数 最后增加第三个参数 来计数。

    可以证明 方案不重不漏.

    //#include<bitsstdc++.h>
    #include<iostream>
    #include<iomanip>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<ctime>
    #include<cmath>
    #include<cctype>
    #include<cstdlib>
    #include<queue>
    #include<deque>
    #include<stack>
    #include<vector>
    #include<algorithm>
    #include<utility>
    #include<bitset>
    #include<set>
    #include<map>
    #define ll long long
    #define db double
    #define INF 1000000000
    #define inf 100000000000000000ll
    #define ldb long double
    #define pb push_back
    #define get(x) x=read()
    #define gt(x) scanf("%d",&x)
    #define put(x) printf("%d
    ",x)
    #define putl(x) printf("%lld
    ",x)
    #define gc(a) scanf("%s",a+1)
    #define rep(p,n,i) for(RE ll i=p;i<=n;++i)
    #define go(x) for(ll i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]])
    #define fep(n,p,i) for(RE ll i=n;i>=p;--i)
    #define pii pair<ll,ll> 
    #define mk make_pair
    #define RE register
    #define S second
    #define gf(x) scanf("%lf",&x)
    #define pf(x) ((x)*(x))
    #define ull unsigned long long
    #define mod 1000000007
    #define ui unsigned
    #define P 13331ll
    using namespace std;
    char buf[1<<15],*fs,*ft;
    inline char getc()
    {
        return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
    }
    inline ll read()
    {
        register ll x=0,f=1;register char ch=getc();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();}
        return x*f;
    }
    const ll MAXN=100010;
    ll n,ans,len;
    ll x,y,z;
    ll f[MAXN],vis[MAXN];
    ll lin[MAXN],ver[MAXN<<1],nex[MAXN<<1],e[MAXN<<1];
    priority_queue<pii>q;
    inline void add(ll x,ll y,ll z)
    {
    	ver[++len]=y;
    	nex[len]=lin[x];
    	lin[x]=len;
    	e[len]=z;
    }
    signed main()
    {
    	//freopen("1.in","r",stdin);
    	get(n);get(x);get(y);get(z);
    	if(x==1||y==1||z==1){putl(n);return 0;}
    	memset(f,-1,sizeof(f));
    	f[1]=1;q.push(mk(1,1));
    	rep(0,z-1,i)add(i,(i+y)%z,y),add(i,(i+x)%z,x);
    	while(q.size())
    	{
    		ll x=q.top().S;q.pop();
    		if(vis[x])continue;
    		vis[x]=1;
    		go(x)
    		{
    			if(f[tn]==-1||f[tn]>f[x]+e[i])
    			{
    				f[tn]=f[x]+e[i];
    				q.push(mk(-f[tn],tn));
    			}
    		}
    	}
    	rep(0,z-1,i)if(f[i]!=-1&&n>=f[i])ans=(ans+(n-f[i])/z+1);
    	putl(ans);return 0;
    }
    
  • 相关阅读:
    JSP数据交互(一)
    response.setHeader()用法
    Vue初步认识
    Socket初步了解
    DOM4j的修改删除方式
    多线程
    ArrayList和Vector区别
    集合框架(一)
    深入C#数据类型
    深入.NET框架
  • 原文地址:https://www.cnblogs.com/chdy/p/12722386.html
Copyright © 2011-2022 走看看