牛客練習賽42題解

2022-05-01 21:09:08 字數 3528 閱讀 1588

寫題寫的感覺自己彷彿是個傻子

給定兩個等長的由小寫字母構成的串 a,b,其中 $ |a|=|b|=n $

現在你需要求出乙個子區間 \([l,r]\)

使得$ lcp(a[l,r],b[l,r])×lcs(a[l,r],b[l,r])+lcp(a[l,r],b[l,r])+lcs(a[l,r],b[l,r])$ 最大,並輸出這個值。

\(lcp(s,t)\)表示s和t的最長公共字首,\(lcs(s,t)\)表示s和t的最長公共字尾。

考慮貪心,因為區間的左右端點可以任意選取,直接處理出premax和sufmax,然後貪心即可

注意lcp和lcs重合的情況

#include #include #include #define int long long

#define ull unsigned long long

using namespace std;

const int base=131;

const int maxn = 200010;

ull hasha[maxn],hashb[maxn],pows[maxn];

char a[maxn],b[maxn];

int n,maxpre[maxn],maxsuf[maxn],pre[maxn],suf[maxn];

ull hashax(int l,int r)

ull hashbx(int l,int r)

void get_hasha(void)

void get_hashb(void)

int ans=0;

signed main()

else

else}}

last=n;

for(int i=n;i>=1;i--)

else

else}}

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

maxpre[i]=max(maxpre[i-1],pre[i]);

for(int i=n;i>=1;i--)

maxsuf[i]=max(maxsuf[i+1],suf[i]);

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

ans=max(ans,maxpre[i]*maxsuf[i]+maxpre[i]+maxsuf[i]);

printf("%lld\n",ans);

return 0;

}

注意本題有模數

給定乙個 長度為 n 的序列 $ $,求:

\[max_\⊕a_⊕\dots⊕a_j)+(a_i+a_+a_+\dots+a_j)\}

\]考慮乙個結論,選上乙個新的數,得到的答案絕對不會更劣,所以選上全部即可

#include #include #include #define int long long

using namespace std;

const int mod = 100000007;

int xorx=0,sumx=0,n;

signed main()

printf("%lld",(xorx%mod+sumx%mod)%mod);

return 0;

}

給定m個長為n的序列a1,a2,…,ama1,a2,…,am。

小z想問你:

\(∑_^n∑_^n\dots∑_^nsum(a_,a_,…,a_) mod(1000000007)\)

其中sum(乙個序列)sum(乙個序列)表示這個序列中所有不同的數的和,相當於先sort,unique再求和。

正向不好考慮,可以反向考慮,思考每個值對答案產生貢獻的次數,等價於求這個數至少被選中一次的方案數,轉化一下就是求總方案數-一次都不選中的方案數,假設乙個值\(v\),在第一行出現\(x_1\)次,在第二行出現\(x_2\)次,在第n行出現\(x_n\)次

則它的貢獻次數就是\(time=m^n-(m-x_1)(m-x_2)\dots(m-x_n)\)

然後沒了

#include #include #include #include #define int long long

using namespace std;

const int mod = 1000000007;

int a[2010][2010],n,m,barrel[2010],ans=0;

vector> vec;

int pow(int a,int b)

return ans;

}int inv[4000];

signed main()^np[i]∗(n+1)^i \ mod 1000000007(10^9+7)​\) ,其中 p 是你求出的排列。

題目保證有解,所以考慮最後的序列形態

第n大的如果放到第一位,會產生n-1個逆序對,同理,同時為滿足字典序最大,前面的一定是一段n~n-x的連續序列,之後為滿足剩下的逆序對數,第k+1大的數一定會被放到n-x的後面,然後是兩端遞增的序列1 ~ k,k+2 ~ n-x-1,然後x可以二分求出,k+1大的數可以直接算出,剩下的使用等比數列求和即可得出結果

#include #include #include #define int long long

using namespace std;

const int mod = 1000000007;

int n,k,ans;

int pow(int a,int b)

return ans;

}int solve(int start,int l,int r)

signed main()

// printf("%lld\n",midans);

k-=(2*n-midans-1)*midans/2;//(n~(n-mid))

// ans=(ans+solve(1,n-midans+1,n))%mod;

// printf("%lld ",solve(1,n-midans+1,n));

ans=(ans+(pow(n+1,midans)-1)*(n+1)-solve(1,0,midans-1)+mod)%mod;

ans=(ans+solve(midans+1,k+1,k+1))%mod;

// printf("%lld ",solve(midans+1,k+1,k+1)); //x=k+1

ans=(ans+solve(midans+2,1,k))%mod;

// printf("%lld ",solve(midans+2,1,k)); //1~x-1,x+1~n-mid-1

ans=(ans+solve(midans+2+k,k+2,n-midans))%mod;

// printf("%lld ",solve(midans+2+k,k+2,n-midans));

printf("%lld\n",(ans+mod)%mod);

return 0;

}

牛客練習賽42(A,B)

時間限制 c c 1秒,其他語言2秒 空間限制 c c 262144k,其他語言524288k 64bit io format lld 給定兩個等長的由小寫字母構成的串 a,ba,b,其中 a b n 現在你需要求出乙個子區間 l,r 使得 lcp a l,r b l,r lcs a l,r b l...

牛客練習賽22題解

簡單瞎搞題 不會用bitset,所以沒做出來。實際上還是比較簡單的。include using namespace std bitset 1000005 dp 2 int main cout 2 count 簡單資料結構1 這裡要運用拓展尤拉定理。ab modp ab p b p p 0 modp ...

題解 牛客練習賽51

字首a的數量,字尾c的數量,遇到b就計算一次答案。includeusing namespace std typedef long long ll const int n 1e5 100 char s n int cnt n int main int tmp 0 for int i 1 i n i p...