省隊集訓DAY6

2021-08-02 02:30:32 字數 1957 閱讀 7785

f[i]表示以字元i結尾的字串的個數。

那麼現在加入乙個字元產生的貢獻就是∑字

符集大小

i=0f

[i] ,然後把這個答案賦值給這個字元對應的位置。

考慮這麼做會不會產生相同的串?假設acbb,考慮插入第乙個b的影響會形成ab,cb,acb.那麼插入第二個b會形成abb,cbb,acbb發現這些都是新產生的不會與之前的相同,而且不會影響到a,c結尾的字串。

那麼每次轉移實際上是乘上了乙個對角線為1,某一列為1為1的矩陣。

我們可以維護矩陣的字首積,和逆矩陣的字首積。

那麼對於每次詢問都可以看成是兩個矩陣相乘。

因為矩陣是沒有交換率的,所以正矩陣維護成a1

,a2,

a3..

. 的形式

對於逆矩陣,我們要保證in

v3,i

nv2,

inv1

順次與a中對應的矩陣相乘。所以每次更新的時候是in

v[i]

=mul

(rs[

x],i

nv[i

−1])

,rs[

i]表示字元x的逆矩陣。 in

v3∗i

nv2∗

inv1

∗a1∗

a2∗a

3 這樣順次相消。

如何求乙個矩陣的逆矩陣?

什麼是逆矩陣?a∗

a−1=

e 其中e表示單位矩陣,那麼a−

1 是

a 的逆矩陣。

首先將逆矩陣賦值為單位矩陣,然後對a進行高斯消元,將a矩陣變成單位矩陣,變換過程中對a矩陣的所有操作都在逆矩陣中同等實現。做完後的逆矩陣即為所求。

如果最後無法消成單位矩陣,那麼說明該矩陣不存在逆矩陣。

#include

#include

#include

#include

#include

#define n 10

#define p 1000000007

#define ll long long

using namespace std;

struct database[n+3],inv[n+3],ans,sum[100003],sinv[100003];

int n,m; char s[100003];

data mul(data a,data b)

return c;

}ll quickpow(ll num,int

x) return ans;

}void guass(data a,data &inv)

ll t=quickpow(a.a[i][i],p-2);

for (int j=1;j<=n;j++)

for (int j=1;j<=n;j++)

if (i!=j&&a.a[j][i]) }}

}int main()

ans.a[1][1]=1;

for (int i=1;i<=n;i++) sinv[0].a[i][i]=1;

sum[1]=base[s[1]-'a'+1];

sinv[1]=inv[s[1]-'a'+1];

for (int i=2;i<=n;i++)

sum[i]=mul(sum[i-1],base[s[i]-'a'+1]),

sinv[i]=mul(inv[s[i]-'a'+1],sinv[i-1]);

scanf("%d",&m);

for (int i=1;i<=m;i++)

}

省隊集訓day6 C

給定平面上的 n 個點,其中有一些是紅的,其他是藍的.現在讓你找兩條平行的直線,使得在保證 不存在乙個藍色的點 被夾在兩條平行線之間,不經過任何乙個點,不管是藍色點還是紅色點 的前提下,被夾在平行線之間的紅色點個數最多 第1行 乙個整數 n 1 n 1000 第2.n 1行 每行是乙個點的座標以及它...

省隊集訓Round3 DAY6

這道題應該是可以通過組合數直接計算的,但是我不會數學證明,所以就用了一種簡單粗暴的方式。an s 2 ic n,i c n n i an s 2 ic n,i 2 101 8 肯定不能直接列舉,如果要計算的話也需要用到lucas定理。觀察發現這題的模數比較小,所以從模數入手。考慮lucas定理。n ...

省隊集訓DAY2

假設我們列舉數列中長度為len的區間,那麼如何判斷兩個數列可以匹配呢?對於提取的數列從小到大排序,從大到小排序,然後兩兩配對,如果所有的都滿足 h 那麼就可以匹配。應該算是貪心吧。這樣做的時間複雜度是o n le n loglen 還是上面的思想,我們如何快速判斷呢?假設我們確定了提取出的區間數列,...