我真不想写背景

来源:互联网 发布:网络连接发生意外错误 编辑:程序博客网 时间:2024/03/29 23:01

我真不想写背景


题目描述

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


输入格式

输入的第一行包含 3 个正整数,分别表示 NBMinBMax 分别表示数列的长度、B 的下界、B 的上界。
输入的第二行包含 N 个整数,即数列 an 的值。


输出格式

输出一个整数,表示有多少 B 可以使等式存在非负整数解。


样例输入

2 5 10
3 5


样例输出

5


样例解释

对于 B=5,式子有 x1=0,x2=1
对于 B=6,式子有 x1=2,x2=0
对于 B=7,无解。
对于 B=8,式子有 x1=1,x2=1
对于 B=9,式子有 x1=3,x2=0
对于 B=10,式子有 x1=0,x2=2


数据范围

20% 的数据,N51BMinBMax10
40% 的数据,N101BMinBMax106
100% 的数据,N120ai41051BMinBMax1012


Solution

因为 B 的范围很大,所以我们考虑将其取模。
对于模 a1 的完全剩余系中的每一个元素 y,若能找到最小的能够表示为

m=i=2naixi
m mod a1=y
m,则对于范围内的任意一个与 y 关于模 a1 同余的 B 都满足
B=ka1+m

则对于每一个 y,可以算出范围内的与 y 关于模 a1 同余的 B 的个数为
bmaxma1Max(bminma1,0)+1

那么,如何求出 m 呢?
my(moda1)

my=ka1

i=2naixika1=y

现已知 y1,枚举 ak,则可以更新 (y1+ak) mod a1
fi 表示 i 所对应的 m 要变成 i 需要减去多少个 a1
f(y1+ak) mod a1=fy1+((y1+ak)((y1+ak) mod a1)a1)

这就是一个最短路模型,每次用 SPFA 更新当前元素所能更新的元素。


Code

#include <iostream>#include <cstdio>#include <cstring>#include <queue>#include <algorithm>#include <cmath>#define LL long long#define Max(x,y) ((x)>(y)?(x):(y))using namespace std;LL n,bmi,bma,ans;LL a[20],dis[400010];bool in_stack[400010];queue<LL>q;void spfa(){    memset(dis,-1,sizeof dis);    dis[0]=0;q.push(0);in_stack[0]=true;    while(!q.empty()){        LL now=q.front();        q.pop();in_stack[now]=false;        for(LL i=2;i<=n;i++){            LL tmp=now+a[i],qq=0;            while(tmp>a[1]){                tmp-=a[1];                qq++;            }            if(dis[tmp]==-1||dis[tmp]>dis[now]+qq){                dis[tmp]=dis[now]+qq;                if(!in_stack[tmp]){                    in_stack[tmp]=true;                    q.push(tmp);                }            }        }    }}int main(){    freopen("wth.in","r",stdin);    freopen("wth.out","w",stdout);    scanf("%lld%lld%lld",&n,&bmi,&bma);    for(LL i=1;i<=n;i++)scanf("%lld",&a[i]);    sort(a+1,a+n+1);    spfa();    for(LL i=0;i<a[1];i++)if(dis[i]!=-1){        LL tmp=i+dis[i]*a[1];        if(tmp>bma)continue;        ans+=(bma-tmp)/a[1]-Max((LL)(ceil(((double)bmi-tmp)/a[1])),0)+1;    }    printf("%lld\n",ans);    return 0;}
0 0
原创粉丝点击