給定一個\(n\),從\([1,n]\)中等機率取出一個數,再等機率生成一個\(n\)的全排列,再計算這個全排列的函數值,求這個函數值的指望。node
函數表達爲輸入一個全排列,計算其逆序數,再等機率取出一個子序列(能夠是空,能夠是原序列),遞歸計算該子序列的函數值,累加返回。c++
#include <bits/stdc++.h> using namespace std; typedef long long ll; const ll mod=998244353; ll Pow(ll a,ll n){ ll ans=1ll; while(n){ if(n%2){ ans=ans*a%mod; } a=a*a%mod; n/=2; } return ans; } ll inv(ll x){ return Pow(x,mod-2)%mod; } ll n; int main(void){ ll inv9=inv(9); while(~scanf("%lld",&n)){ printf("%lld\n",(Pow(n,2)-1)*inv9%mod); } return 0; }
給定一個字符串,詢問\(1-n\)每種長度的迴文子串有多少個,且必須知足前半部分也是迴文串。函數
#include <bits/stdc++.h> using namespace std; typedef long long ll; typedef unsigned ull; const int N=3e5+50; const ull base=19260817; int ans[N]; ull has[N],pw[N]; void initHash(){ pw[0]=1; for(int i=1;i<N;i++){ pw[i]=pw[i-1]*base; } } ull getHash(int l,int r){ return has[r]-has[l-1]*pw[r-l+1]; } //判斷迴文串[l,r],先後兩部分是否相等,如果,說明是迴文 bool check(int l,int r){ int len=r-l+1; int mid=(l+r)/2; return getHash(l,mid)==getHash((len%2?mid:mid+1),r); } struct PT{ int next[N][26],fail[N],cnt[N],num[N],len[N]; int S[N],last,id[N],n,p; int newnode(int l){ for(int i=0;i<26;i++){ next[p][i]=0; } cnt[p]=num[p]=0; len[p]=l; return p++; } void init(){ p=0; //先0再-1 這樣-1(p=1)的兒子就是0(p=0),後面0(p=0)的fail就是-1(p=1) newnode(0); newnode(-1); last=0; n=0; S[n]=-1; fail[0]=1; } int getFail(int x){ while(S[n-len[x]-1]!=S[n]){ x=fail[x]; } return x; } void add(int c){ c-='a'; S[++n]=c; int cur=getFail(last); if(!next[cur][c]){ int now=newnode(len[cur]+2); fail[now]=next[getFail(fail[cur])][c]; num[now]=num[fail[now]]+1; next[cur][c]=now; } last=next[cur][c]; cnt[last]++; id[last]=n; } void count(){ for(int i=p-1;i>=0;i--){ cnt[fail[i]]+=cnt[i]; } } void getAns(){ for(int i=2;i<p;i++){ //枚舉每一個節點 if(check(id[i]-len[i]+1,id[i])){ ans[len[i]]+=cnt[i]; } } } }ac; char s[N]; int main(void){ // freopen("in.txt","r",stdin); initHash(); while(~scanf("%s",s+1)){ int n=strlen(s+1); ac.init(); has[0]=0; for(int i=1;i<=n;i++){ ac.add(s[i]); //這裏記得別寫成*10 has[i]=has[i-1]*base+(s[i]-'a'); } memset(ans,0,sizeof(ans)); ac.count(); ac.getAns(); for(int i=1;i<=n;i++){ printf("%d%c",ans[i],i==n?'\n':' '); } } return 0; }
經過詢問肯定一個數\(x\),每次詢問\(y_i\),回答\(x\&y_i\)是否等於\(y_i\),問最少詢問次數的方案數。ui
顯然是每次詢問肯定一位是最優的,能夠經過計算指望證實。spa
因此\(x\)有\(n\)位數,就是有\(n!\)種不一樣的詢問排列來肯定這個數。code
當\(n>1e6+3\)時,\(n!\)確定含有因子\(1e6+3\),所以結果爲0。遞歸
#include <bits/stdc++.h> using namespace std; typedef long long ll; const ll mod=1e6+3; ll n; int main(void){ while(~scanf("%lld",&n)){ //n>=1e6+3 n!確定含有1e6+3這個因子,因此結果必定爲0 if(n>=1000003){ printf("0\n"); continue; } ll ans=1ll; for(ll i=2ll;i<=n;i++){ ans=ans*i%mod; } printf("%lld\n",ans); } return 0; }
給n個棍子,屢次詢問區間內能組成三角形的最大周長。ip
若是不考慮不能組成三角形的狀況,那麼答案就是區間內前三大的值之和。字符串
考慮有不能組合的狀況,仍然是從大到小貪心地判斷下一組可否組成三角形。get
長度在1e9範圍內,連續判斷的次數不會超過44次。
證實就是斐波那契數列,假設連續的\(n\)個長度都不能組成三角形(1,1,10000000...這種確定能夠),假設長度增加很慢,每次都只是恰好前兩個木棍的和,那麼這就是斐波那契數列,而第45項斐波那契數列已經超過了1e9
因此用主席樹查詢區間第k小。
#include <bits/stdc++.h> using namespace std; #define mid (l+r)/2 typedef long long ll; const int N=1e5+50; int tr[N*30],sum[N*30],lr[N*30],rr[N*30]; int n,q,a[N],b[N],l,r; int cnt; int build(int l,int r){ int rt=++cnt; sum[rt]=0; if(l==r){ return rt; } lr[rt]=build(l,mid); rr[rt]=build(mid+1,r); return rt; } int update(int pre,int l,int r,int x){ int rt=++cnt; lr[rt]=lr[pre]; rr[rt]=rr[pre]; sum[rt]=sum[pre]+1; if(l==r){ return rt; } if(x<=mid){ lr[rt]=update(lr[pre],l,mid,x); }else{ rr[rt]=update(rr[pre],mid+1,r,x); } return rt; } int kth(int a,int b,int l,int r,int k){ if(l>=r){ return l; } int x=sum[lr[b]]-sum[lr[a]]; if(k<=x){ return kth(lr[a],lr[b],l,mid,k); }else{ return kth(rr[a],rr[b],mid+1,r,k-x); } } int main(void){ // freopen("in.txt","r",stdin); while(~scanf("%d%d",&n,&q)){ for(int i=1;i<=n;i++){ scanf("%d",&a[i]); b[i]=a[i]; } //權值建樹記得離散化 sort(b+1,b+1+n); int m=unique(b+1,b+1+n)-b-1; //多組記得初始化 cnt=0; //離散化後範圍記得是m tr[0]=build(1,m); for(int i=1;i<=n;i++){ a[i]=lower_bound(b+1,b+1+m,a[i])-b; tr[i]=update(tr[i-1],1,m,a[i]); } while(q--){ scanf("%d%d",&l,&r); int len=r-l+1; ll ans=-1; while(len>=3){ int aa=b[kth(tr[l-1],tr[r],1,m,len)]; int bb=b[kth(tr[l-1],tr[r],1,m,len-1)]; int cc=b[kth(tr[l-1],tr[r],1,m,len-2)]; if(aa>=bb+cc){ len--; continue; } ans=1ll*aa+1ll*bb+1ll*cc; break; } printf("%lld\n",ans); } } return 0; }