• [BZOJ2118]墨墨的等式


    [BZOJ2118]墨墨的等式

    试题描述

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

    输入

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

    输出

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

    输入示例

    2 5 10
    3 5

    输出示例

    5

    数据规模及约定

    对于100%的数据,N≤12,0≤ai≤5*10^5,1≤BMin≤BMax≤10^12。

    题解

    这题的思路我也不知道怎么想到的。。。

    就是选一个数 a1,然后以它为基础做,显然所有能被拼凑出来的数都可以表示成这个形式:ki · a1 + i,然后对于每个 i 我们可以求出最小的 ki,那么 (ki + 1) · a1 + i,(ki + 2) · a1 + i,(ki + 3) · a1 + i,...,都是可以被表示出来的,那么对于能够凑出来的数模 a1 等于 i 的这一部分答案就可以用除法统计出来了。

    那么如何算最小的 ki,这就是一个最短路,总共有 n 种转移,每种转移边权为 ai

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cctype>
    #include <algorithm>
    #include <queue>
    using namespace std;
    #define LL long long
    
    LL read() {
    	LL x = 0, f = 1; char c = getchar();
    	while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
    	while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
    	return x * f;
    }
    
    #define maxn 500010
    #define oo (1ll << 60)
    
    int n, A[15];
    LL Bl, Br, K[maxn];
    
    struct Node {
    	LL val;
    	Node() {}
    	Node(LL _): val(_) {}
    	bool operator < (const Node& t) const { return val > t.val; }
    };
    priority_queue <Node> Q;
    bool vis[maxn];
    void solve() {
    	for(int i = 0; i < A[1]; i++) K[i] = oo;
    	K[0] = 0; Q.push(Node(0));
    	while(!Q.empty()) {
    		Node u = Q.top(); Q.pop();
    		if(vis[u.val%A[1]]) continue;
    		vis[u.val%A[1]] = 1;
    		for(int i = 1; i <= n; i++) if(K[(u.val+A[i])%A[1]] > (u.val + A[i]) / A[1]) {
    			K[(u.val+A[i])%A[1]] = (u.val + A[i]) / A[1];
    			if(!vis[(u.val+A[i])%A[1]]) Q.push(Node(u.val + A[i]));
    		}
    	}
    	return ;
    }
    
    LL Div(LL a, LL b) {
    	int fl = 1;
    	if(a < 0) fl = -fl;
    	if(b < 0) fl = -fl;
    	if(fl > 0) return a / b;
    	if(a % b) return a / b - 1;
    	return a / b;
    }
    
    int main() {
    	n = read(); Bl = read() - 1; Br = read();
    	for(int i = 1; i <= n; i++) A[i] = read();
    	
    	solve();
    	LL ans = 0;
    	for(int i = 0; i < A[1]; i++) {
    		LL xl = Div(Bl - i, (LL)A[1]) + 1, xr = Div(Br - i, (LL)A[1]);
    		if(xr >= max(xl, K[i])) ans += xr - max(xl, K[i]) + 1;
    	}
    	printf("%lld
    ", ans);
    	
    	return 0;
    }
    /*
    in:
    10 2333 666666666666
    100000 2342 32768 500000 36 216 1296 7776 46656 279936
    out:
    333333323324
    */
    
  • 相关阅读:
    写给自己的2020年总结
    docker镜像与docker容器
    docker安装&docker简介
    windows 安装linux子系统
    typora设置图床
    让Mysql插入中文
    pip 换源
    Unity中如何将一个场景(Scene)的Light Settings复制给另一个场景
    Windows API开发
    【C#】判断字符串中是否包含指定字符串,contains与indexOf方法效率问题
  • 原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/6649871.html
Copyright © 2020-2023  润新知