zoukankan      html  css  js  c++  java
  • 【LOJ】#2523. 「HAOI2018」奇怪的背包

    题解

    复杂度怎么算也要2s的题怎么0.5s就跑完了,迷啊

    这个题简直算完复杂度不敢写,写了就赚飞了好吧

    根据裴蜀定理,显然选出的数和P的gcd是w的约数

    我们考虑枚举(P)的约数,上限当然是(sqrt{P})个,写个暴力搜一下发现最多也就13000个左右

    然后我们把每个数处理成(gcd(a_i,P))

    重标号所有约数

    那么我们写个(n^2)(dp[i][j])表示处理到第(i)个约数,然后这些数的(gcd)是第(j)个约数

    然后再(n^2)(val[j])的约数(val[i])(dp[tot][i])累加进(ans[j])

    查询的时候看看(gcd(w_i,P))是哪个约数就行

    代码

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define pii pair<int,int>
    #define pdi pair<db,int>
    #define mp make_pair
    #define pb push_back
    #define enter putchar('
    ')
    #define space putchar(' ')
    #define eps 1e-8
    #define MAXN 100005
    #define mo 974711
    //#define ivorysi
    using namespace std;
    typedef long long int64;
    typedef double db;
    template<class T>
    void read(T &res) {
        res = 0;char c = getchar();T f = 1;
        while(c < '0' || c > '9') {
    	if(c == '-') f = -1;
    	c = getchar();
        }
        while(c >= '0' && c <= '9') {
    	res = res * 10 + c - '0';
    	c = getchar();
        }
        res *= f;
    }
    template<class T>
    void out(T x) {
        if(x < 0) {x = -x;putchar('-');}
        if(x >= 10) {
    	out(x / 10);
        }
        putchar('0' + x % 10);
    }
    const int MOD = 1000000007;
    int inc(int a,int b) {
        return a + b >= MOD ? a + b - MOD : a + b;
    }
    int mul(int a,int b) {
        return 1LL * a * b % MOD;
    }
    int update(int &x,int y) {
        x = inc(x,y);
    }
    int N,Q,P;
    struct node {
        int x,num,next;
    }E[100005];
    int head[mo + 5],sumE,val[13005],tot,pw[1000005],cnt[13005];
    int f[2][13005],ans[13005];
    void add(int x,int y) {
        int u = x % mo;
        E[++sumE].x = x;
        E[sumE].num = y;
        E[sumE].next = head[u];
        head[u] = sumE;
    }
    int Query(int x) {
        int u = x % mo;
        for(int i = head[u] ; i ; i = E[i].next) {
    	if(E[i].x == x) return E[i].num;
        }
    }
    int gcd(int a,int b) {
        return b == 0 ? a : gcd(b,a % b);
    }
    void Init() {
        read(N);read(Q);read(P);
        for(int i = 1 ; i <= P / i ; ++i) {
    	if(P % i == 0) {
    	    val[++tot] = i;
    	    if(i != P / i) val[++tot] = P / i;
    	}
        }
        sort(val + 1,val + tot + 1);
        for(int i = 1 ; i <= tot ; ++i) add(val[i],i);
        pw[0] = 1;
        int a;
        for(int i = 1 ; i <= N ; ++i) {
    	pw[i] = mul(pw[i - 1],2);
    	read(a);cnt[Query(gcd(a,P))]++; 
        }
    }
    void Solve() {
        int cur = 0;
        f[cur][Query(P)] = 1;
        for(int i = 1 ; i <= tot ; ++i) {
    	if(!cnt[i]) continue;
    	memset(f[cur ^ 1],0,sizeof(f[cur ^ 1]));
    	for(int j = 1 ; j <= tot ; ++j) {
    	    update(f[cur ^ 1][Query(gcd(val[i],val[j]))],mul(f[cur][j],pw[cnt[i]] - 1));
    	    update(f[cur ^ 1][j],f[cur][j]);
    	}
    	cur ^= 1;
        }
        for(int i = 1 ; i <= tot ; ++i) {
    	for(int j = 1 ; j <= i ; ++j) {
    	    if(val[i] % val[j] == 0) update(ans[i],f[cur][j]);
    	}
        }
        int w;
        for(int i = 1 ; i <= Q ; ++i) {
    	read(w);
    	out(ans[Query(gcd(w,P))]);enter;
        }
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Init();
        Solve();
    }
    
  • 相关阅读:
    使用百度字体编辑器删除不必要字体,减少字体文件体积
    使用npm安装webpack失败时,可能被墙要为cmd命令行设置代理
    让字体图标代替雪碧图,减少请求带宽
    隐藏浏览器原生的滚动条
    台式机安装CentOS7.6 Minimal ISO系统并增加图形化桌面
    像我这样笨拙地生活(廖一梅)--节选
    随心随意亦舒经典语录
    file / from install of XXX conflicts with file from package filesystem-XXX
    nginx代理php项目的websocket
    Redis4配置文件详解
  • 原文地址:https://www.cnblogs.com/ivorysi/p/10030065.html
Copyright © 2011-2022 走看看