bzoj 2118: 墨墨的等式

Description

墨墨突然对等式很感兴趣,他正在研究a1x1+a2y2+…+anxn=B存在非负整数解的条件,他要求你编写一个程序,给定N、{an}、以及B的取值范围,求出有多少B可以使等式存在非负整数解。

Solution

选择任意一个正整数\(a_i\),作为 \(x*a_i\) 的底数,然后假如我们知道了最小满足 \(B \% a_i=k\)\(B\),那么大于 \(B\) 的满足与 \(B\) 同余的也一定能够凑出来
所以我们只需要对于每一个余数,求出 \(dis[i]\) 表示用 \(a_1....a_n\) 能够凑出的满足 \(B%a_i=i\) 的最小的 \(B\) 为多少
然后对于每一个剩余类,分别算答案即可,可以保证不重不漏
最后答案就是 \(solve(BMax)-solve(BMin-1)\)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=15;
int n,a[N],p=1;ll L,R,dis[500005];
queue<int>Q;bool vis[500005];
inline void spfa(){
    for(int i=0;i<a[p];i++)dis[i]=1e13;
    dis[0]=0;vis[0]=1;Q.push(0);
    while(!Q.empty()){
        int x=Q.front();Q.pop();
        for(int i=1;i<=n;i++){
            int u=(x+a[i])%a[p];
            if(dis[x]+a[i]<dis[u]){
                dis[u]=dis[x]+a[i];
                if(!vis[u])vis[u]=1,Q.push(u);
            }
        }
        vis[x]=0;
    }
}
inline ll calc(ll x,int k){
    return (x-k)/a[p]+1;
}
inline ll solve(ll mid){
    ll ret=0;
    for(int i=0;i<a[p];i++)
        if(dis[i]<=mid)ret+=calc(mid,i)-calc(dis[i]-1,i);
    return ret;
}
int main(){
  freopen("pp.in","r",stdin);
  freopen("pp.out","w",stdout);
  scanf("%d%lld%lld",&n,&L,&R);
  for(int i=1;i<=n;i++)scanf("%d",&a[i]);
  sort(a+1,a+n+1);
  if(a[n]==0){puts("0");return 0;}
  while(!a[p])p++;spfa();
  printf("%lld\n",solve(R)-solve(L-1));
  return 0;
}

转载于:https://www.cnblogs.com/Yuzao/p/8481342.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值