奇怪的背包

奇怪的背包

有一个背包,有一个模数P,有n件物品,第i件物品体积为\(v_i\),物品可以无限取用,最后背包的体积为总体积\(mod\ p\),q组询问,第i个询问背包最终体积为\(w_i\)的方案数,两个方案数的不同不在于物品的放的个数,而在于物品是否取用。

\(n,q\leq 10^6,p\leq 10^9\)

显然物品的取用的次数没有关系,那么关键在于物品是否取用,以及它能到达的背包体积,于是对于一件物品不难写出式子

\[kv_i=z(mod\ p)\]

k为取用的个数,z为得到的背包体积,于是由bezaut定理得知,它能所取用的背包的体积一定为\(gcd(p,v_i)\)的倍数,而同理推广多个数自然为
\(gcd(v_1,v_2,...,v_n,p)\)的倍数。

于是把各个\(gcd(p,v_i)\)维护为\(d[i]\),个数为\(s[j]\),显然只有p的约数个数种,所以不难得知我们应设递推方程\(f[i][j]\)表示选到第i件物品,现在最大公约数为\(d[j]\)的方案数,现在暂时把n改成p的约数个数,所以又不难有

\[f[i][j]=f[i-1][j]+\sum_{k=1}^nf[i-1][k]\times (gcd(d[k],d[i])==d[j])(2^{s[i]-1})\]

以此可以转移,于是对于询问我们的答案统计为

\[ans=\sum_{j=1}^nf[j][w_i]\]

注意到我们不能每次\(\sqrt{p}\)回答询问,于是我们设法维护出结果,\(O(1)\)回答,显然暴力维护只有p的约数个数平方。

参考代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
#define il inline
#define ri register
#define ll long long
#define yyb 1000000007
#define _ putchar('\n')
#define swap(x,y) x^=y^=x^=y
using namespace std;
ll lsy,d[5000],dt,s[5000],cjx,
    bin[1000001],dp[2][5000],ask[5000];
il void fact(ll);
il int dfs(ll);
il ll gcd(ll,ll);
template<class free>void pen(free);
template<class free>il void read(free&);
int main(){
    int n,q,i,j;bool now(false);
    read(n),read(q),read(lsy),fact(lsy);
    for(i=bin[0]=1;i<=n;++i)read(cjx),++s[dfs(gcd(lsy,cjx))],
                                bin[i]=(bin[i-1]<<1)%yyb;
    for(i=1;i<=dt;++i)s[i]=(bin[s[i]]+yyb-1)%yyb;
    for(i=1;i<=dt;++i,now^=1){
        dp[now][i]=s[i];
        for(j=1;j<=dt;++j)
            dp[now^1][j]=dp[now][j],
                (dp[now^1][dfs(gcd(d[i+1],d[j]))]+=dp[now][j]*s[i+1])%=yyb;
    }
    for(i=1;i<=dt;++i)
        for(j=1;j<=i;++j)
            if(!(d[i]%d[j]))(ask[i]+=dp[now][j])%=yyb;
    while(q--)read(cjx),pen(ask[dfs(gcd(cjx,lsy))]),_;
    return 0;
}
il int dfs(ll x){
    int l(1),r(dt),mid;
    while(l<=r){
        mid=l+r>>1;
        if(d[mid]<x)l=mid+1;
        else r=mid-1;
    }return l;
}
il void fact(ll x){
    ll i;
    for(i=1;i*i<x;++i)
        if(!(x%i))d[++dt]=i,d[++dt]=x/i;
    if(i*i==x)d[++dt]=i;sort(d+1,d+dt+1);
}
template<class free>
void pen(free x){if(x>9)pen(x/10);putchar(x%10+48);}
il ll gcd(ll a,ll b){while(b)swap(a,b),b%=a;return a;}
template<class free>
il void read(free &x){
    x&=0;ri char c;while(c=getchar(),c<'0'||c>'9');
    while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
}

转载于:https://www.cnblogs.com/a1b3c7d9/p/10839825.html

1. 用户与权限管理模块 角色管理: 学生:查看实验室信息、预约设备、提交耗材申请、参与安全考核 教师:管理课题组预约、审批学生耗材申请、查看本课题组使用记录 管理员:设备全生命周期管理、审核预约、耗材采购与分发、安全检查 用户操作: 登录认证:统一身份认证(对接学号 / 工号系统,模拟实现),支持密码重置 信息管理:学生 / 教师维护个人信息(联系方式、所属院系),管理员管理所有用户 权限控制:不同角色仅可见对应功能(如学生不可删除设备信息) 2. 实验室与设备管理模块 实验室信息管理: 基础信息:实验室编号、名称、位置、容纳人数、开放时间、负责人 功能分类:按学科(计算机实验室 / 电子实验室 / 化学实验室)标记,关联可开展实验类型 状态展示:实时显示当前使用人数、设备运行状态(正常 / 故障) 设备管理: 设备档案:名称、型号、规格、购置日期、单价、生产厂家、存放位置、责任人 全生命周期管理: 入库登记:管理员录入新设备信息,生成唯一资产编号 维护记录:记录维修、校准、保养信息(时间、内容、执行人) 报废处理:登记报废原因、时间,更新设备状态为 "已报废" 设备查询:支持按名称、型号、状态多条件检索,显示设备当前可用情况 3. 预约与使用模块 预约管理: 预约规则:学生可预约未来 7 天内的设备 / 实验室,单次最长 4 小时(可设置) 预约流程:选择实验室→选择设备→选择时间段→提交申请(需填写实验目的) 审核机制:普通实验自动通过,高危实验(如化学实验)需教师审核 使用记录: 签到 / 签退:到达实验室后扫码签到,离开时签退,系统自动记录实际使用时长 使用登记:填写实验内容、设备运行情况(正常 / 异常),异常情况需详细描述 违规管理:迟到 15 分钟自动取消预约,多次违规限制预约权限 4. 耗材与安全管理模块 耗材管理: 耗材档案:名称、规格、数量、存放位置、
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值