SOJ4293 Product

統計大集合A中所有含奇數個元素的子集S中元素乘積的和!(我已經儘量說的很不饒了= =)

設ans1是A中所有奇數集元素積的和(要求的答案),ans2是A中所有偶數集元素積的和。

賦初值,令ans1=0,ans2=1(方便每次從空集變成單元素集的過程)

每個奇數集加入一個元素x後會變成偶數集,其元素積的和會乘以x,偶數集亦然。

這樣每次加入x操作有:

ans1=ans1+ans2*x         (1)

ans2=ans2+ans1*x          (2)

刪除操作時即是已知方程左邊求右邊,用(2)式乘以x減去(1)式,差除以(x*x-1),可以求出新的ans1,同理可求ans2,注意除法要用逆元。


#include <cstdio>
typedef long long ll;

int mod = 1000000007;
int n;
char cmd[10];
ll x,ans1[2],ans2[2];
bool flag;

ll inv(ll xx)
{
    ll res=1;
    int k=mod-2;
    while (k)
    {
        if (k&1) res=(res*xx)%mod;
        xx=(xx*xx)%mod;
        k>>=1;
    }
    return res;
}

int main()
{
    while (scanf("%d",&n)==1)
    {
        ans1[0]=0;
        ans2[0]=1;
        flag=0;
        while (n--)
        {
            flag^=1;
            scanf("%s %lld",cmd,&x);
            if (cmd[0]=='i')
            {
                ans1[flag]=(ans1[flag^1]+(ans2[flag^1]*x)%mod)%mod;
                ans2[flag]=(ans2[flag^1]+(ans1[flag^1]*x)%mod)%mod;
            }
            else
            {
                ans1[flag]=((((ans2[flag^1]*x)%mod-ans1[flag^1]+mod)%mod)*inv((x*x-1)%mod))%mod;
                ans2[flag]=((((((ans1[flag^1])*x)%mod)-ans2[flag^1]+mod)%mod)*inv((x*x-1)%mod))%mod;
            }
            printf("%lld\n",ans1[flag]);
        }
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章