数据结构(set)

【from new_dtoj 3974: 数据结构(set)】
题目描述
对一个可重集合进行操作,每次可以所有元素+1+1或添加一个元素。输出集合元素的kk次方和。(来自jarden神犇)
题解:
对于每个数字xx,可以算出它+1+1的价值:
(x+1)k=Ck0xk+Ck1xk1+...+Ckk(x+1)^k=C_k^0*x^k+C_k^1*x^{k-1}+...+C_k^k
所以用sis_i维护所有数的ii次方和,每次用k2k^2修改,效率O(mk2)O(mk^2)(卡常可过) 也可以写个优化,变成O(mk)O(mk)
具体见代码
1.O(mk2)1.O(mk^2)

#include <cstdio>
#include <string>
#define _(d) while(d(isdigit(c=getchar())))
using namespace std;
inline int R(){
    int x,f=1;char c;_(!)c=='-'?f=0:f;x=(c^48);
    _()x=(x<<3)+(x<<1)+(c^48);return f?x:-x;
}
const int P=1e9+7;int m,k,s[52],c[52][52];
int main(){
    m=R();k=R();for (int i=1;i<=k;i++) c[i][0]=c[0][i]=1;
    for (int i=1;i<=k;i++) for (int j=1;j<=i;j++)
        c[i][j]=(c[i-1][j-1]+c[i-1][j])%P;
    for (int op,x;m--;){
        op=R();if (op) for (int i=k;i;i--)
            for (int j=i-1;j>=0;j--)
                s[i]=(1ll*s[i]+1ll*s[j]*c[i][j]%P)%P;
        else{
            x=R();op=x;s[0]++;s[1]=(1ll*s[1]+x)%P;
            for (int i=2;i<=k;i++)
                x=1ll*op*x%P,s[i]=(1ll*s[i]+x)%P;
        }
        printf("%d\n",s[k]);
    }
    return 0;
}

2.O(mk)2.O(mk)(orzsuzhen)

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
int R(){
    int s=0,p=1; char c=getchar(); while(!isdigit(c)) {if(c=='-') p=-1; c=getchar();}
    while(isdigit(c)) s=s*10+c-'0',c=getchar(); return s*p;
}
typedef long long ll;
const int K=52,N=2e5+2; const ll p=1e9+7;
ll mul(ll a,int x){ll s=1; while(x){if(x&1) s=s*a%p; a=a*a%p; x/=2;} return s;}
int n,m,k; ll y,s1[K],s2[K],s[K],mi[N][K];
ll C(int n,int m){return s1[n]*s2[m]%p*s2[n-m]%p;}
int main()
{
    cin>>m>>k;
    s1[0]=1; for(int i=1;i<=k;i++) s1[i]=s1[i-1]*i%p;
    s2[k]=mul(s1[k],p-2); for(int i=k-1;i>=0;i--) s2[i]=s2[i+1]*(i+1)%p;
    for(int i=0;i<=m;i++){mi[i][0]=1; for(int j=1;j<=k;j++) mi[i][j]=mi[i][j-1]*i%p;}
    while(m--){
        int op=R(); 
        if(!op){
            ll x=R()-y,sum=1; for(int i=0;i<=k;i++) s[i]=(s[i]+sum)%p,sum=sum*x%p;  
        }
        else y++; 
        ll ans=0; 
        for(int i=0;i<=k;i++) ans=(ans+C(k,i)*mi[y][k-i]%p*s[i]%p)%p;
        printf("%lld\n",(ans+p)%p); 
    }
    return 0;
}
posted @ 2018-10-22 16:57  xjqxjq  阅读(462)  评论(0编辑  收藏  举报