A. 李時珍的皮膚衣
看不出規律就打表
點選檢視程式碼
#include <bits/stdc++.h>
#define ll __int128
using namespace std;
long long n;
void p(ll x)
{
if(!x)return;
p(x/10);
cout<<int(x%10);
}
ll qpow(ll a,ll b)
{
ll ans=1;
while(b)
{
if(b&1)ans=ans*a%n;
a=a*a%n;
b>>=1;
}
return ans;
}
int main()
{
freopen("lsz.in","r",stdin);
freopen("lsz.out","w",stdout);
cin>>n;
ll pp=(qpow(2,n-1)+1+n)%n;
if(!pp)cout<<0;
else p(pp);
return 0;
}
B. 馬大嘴的廢話
首先如果用hash話會T
Hash
#include <bits/stdc++.h>
#define ll long long
#define ull long long
using namespace std;
const int N =1e4+5,B=233;
int n,m,len[N];ull ha[N][25],p[25];
string s,x;
void get(int d)
{
len[d]=s.size();
for(int i=1;i<=len[d];i++)
{
ha[d][i]=ha[d][i-1]*B+s[i-1];
}
}
ull Hash(int l,int r,int i)
{
return ha[i][r]-ha[i][l-1]*p[r-l+1];
}
int main()
{
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
freopen("mdz.in","r",stdin);
freopen("mdz.out","w",stdout);
cin>>n;
p[0]=1;
for(int i=1;i<=20;i++)p[i]=p[i-1]*B;
for(int i=1;i<=n;i++)
{
cin>>s;
get(i);
}
cin>>m;
for(int i=1;i<=m;i++)
{
cin>>x;
ull has=0;
int l=x.size();
for(int i=1;i<=l;i++)
{
has=has*B+x[i-1];
}
int ans=0;
for(int j=1;j<=n;j++)
{
if(len[j]<l)continue;
else
{
for(int st=1;st<=len[j]-l+1;st++)
{
if(Hash(st,st+l-1,j)==has)
{
ans++;
break;
}
}
}
}
cout<<ans<<endl;
}
return 0;
}
我們可以考慮字典樹,如何在樹中插入呢,當輸入一個字串時,不能只插入一個整串,這樣不方便查詢,必須把這個字串的子串插入,方便查詢,用一個陣列同步記錄每個字元出現次數
然後需要用陣列記錄一下當前子串屬於那個整串,防止記重
最佳化後
#include <bits/stdc++.h>
#define ll long long
#define ull long long
using namespace std;
const int N =1e4+5,B=233;
int n,m;int son[N*50][27],num[N*50][27],cnt=1;int vis[N*50][27];
string s,x;
void insert(const string &s,int id)
{
int len=s.size()-1,now=1;
for(int i=0;i<=len;i++)
{
int ch=s[i]-'a';
if(!son[now][ch])
{
son[now][ch]=++cnt;
vis[now][ch]=id;
num[now][ch]++;
}else
{
if(vis[now][ch]!=id)num[now][ch]++,vis[now][ch]=id;
}
now=son[now][ch];
}
}
int query(const string &s)
{
int len=s.size()-1,now=1;
int ans=0;
for(int i=0;i<=len;i++)
{
int ch=s[i]-'a';
if(!son[now][ch])
{
return 0;
}
ans=num[now][ch];
now=son[now][ch];
}
return ans;
}
int main()
{
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
freopen("mdz.in","r",stdin);
freopen("mdz.out","w",stdout);
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>s;
int len=s.size()-1;
for(int k=0;k<=len;k++)
{
string tmp=s.substr(k,len-k+1);
insert(tmp,i);
}
}
cin>>m;
for(int i=1;i<=m;i++)
{
cin>>x;
cout<<query(x)<<endl;
}
return 0;
}
/*
*/
D. 清理牛棚
用DP的話,我們設當前狀態為i,f[i]表示0~i所需的最短時間,我們需要和前面區間比較
這是我們可以用線段樹最佳化,維護m到e之間的最小值,這樣動態轉移方程為
\[f[i]=min(f[i],w_i+query(1,l_i-1,r_i))
\]
還有一個注意的點,最後答案右端點比e大的都要比較,quzuiyouzhi
點選檢視程式碼
#include <bits/stdc++.h>
#define ll long long
#define lid (rt<<1)
#define rid (rt<<1|1)
using namespace std;
const int mod = 86399,N=1e4+5;
int n,m,e;
ll sum;
struct ac
{
int st,en,s;
}a[N];
int f[mod*4];
struct tree
{
int l,r,w;
}st[mod*5];
void pushup(int rt)
{
st[rt].w=min(st[lid].w,st[rid].w);
}
void buildtree(int rt,int l,int r)
{
st[rt].l=l;st[rt].r=r;
if(l==r)
{
st[rt].w=f[l];
return;
}
int mid=(l+r)>>1;
buildtree(lid,l,mid);
buildtree(rid,mid+1,r);
pushup(rt);
}
void modify(int rt,int l,int r,int val)
{
if(l<=st[rt].l&&st[rt].r<=r)
{
st[rt].w=val;
return;
}
int mid=(st[rt].l+st[rt].r)>>1;
if(l<=mid)modify(lid,l,r,val);
if(r>mid)modify(rid,l,r,val);
pushup(rt);
}
int query(int rt,int l,int r)
{
if(l<=st[rt].l&&st[rt].r<=r)
{
return st[rt].w;
}
int mid=(st[rt].l+st[rt].r)>>1;
int ans=INT_MAX;
if(l<=mid)ans=min(query(lid,l,r),ans);
if(r>mid)ans=min(query(rid,l,r),ans);
return ans;
}
bool cmp(ac a,ac b)
{
return a.en<b.en;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
// freopen("clean_ex.in","r",stdin);
freopen("clean.in","r",stdin);
freopen("clean.out","w",stdout);
cin>>n>>m>>e;
memset(f,0x3f,sizeof(f));
// for(int i=m;i<=e;i++)f[i]=INT_MAX;
for(int i=1;i<=n;i++)
{
cin>>a[i].st>>a[i].en>>a[i].s;
sum+=a[i].s;
}
sort(a+1,a+1+n,cmp);
f[m]=0;
buildtree(1,m,e);
for(int i=1;i<=n;i++)
{
// int ch=a[i].en-a[i].st+1;
f[a[i].en]=min(f[a[i].en],query(1,a[i].st-1,a[i].en)+a[i].s);
modify(1,a[i].en,a[i].en,f[a[i].en]);
if(a[i].en>=e)
{
if(f[a[i].en]>sum)cout<<-1;
else cout<<f[a[i].en];
return 0;
}
// for(int k=st;k<=i;k++)f[k]=min(f[i],f[k]);
}
return 0;
}
/*
3 0 4
0 2 3
3 4 2
0 0 1
*/
E. 歷史研究
- 開longlong
- 注意細節
- 要離散化
先說分塊的做法,首先分塊,按塊預先處理處每個元素出現次數的字首和,然後預先處理處i~j塊之間的答案編號
查詢時,我們用桶記錄出現次數與重要度的乘積,散塊暴力,整塊直接出答案(記的加上分塊中的),然後比較哪個最大即可
點選檢視程式碼
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N =1e5+5;
int n,q,sq,st[500],en[500],belong[N],tot,ans[500][500];
ll b[N],a[N],cnt[500][N];map <ll,int> mp;
void init()
{
sq=sqrt(n);
for(int i=1;i<=sq;i++)
{
st[i]=n/sq*(i-1)+1;
en[i]=n/sq*i;
}
en[sq]=n;
for(int i=1;i<=sq;i++)
{
for(int j=st[i];j<=en[i];j++)
{
belong[j]=i;
}
}
for(int i=1;i<=sq;i++)
{
for(int j=1;j<=n;j++)cnt[i][j]=cnt[i-1][j];
for(int j=st[i];j<=en[i];j++)
{
cnt[i][a[j]]++;
}
}
ll res=0,id=0;
for(int i=1;i<=sq;i++)
{
for(int j=i;j<=sq;j++)
{
ans[i][j]=ans[i][j-1];
res=b[ans[i][j]]*(cnt[j][ans[i][j]]-cnt[i-1][ans[i][j]]);
id=ans[i][j-1];
for(int k=st[j];k<=en[j];k++)
{
int p=a[k];
if(res<b[p]*(cnt[j][p]-cnt[i-1][p]))
{
res=b[p]*(cnt[j][p]-cnt[i-1][p]);
id=p;
}
}
ans[i][j]=id;
}
}
}
ll tong[N];
ll query(int l,int r)
{
ll Ans=0;
if(belong[l]==belong[r])
{
for(int i=l;i<=r;i++)
{
tong[a[i]]+=b[a[i]];
Ans=max(Ans,tong[a[i]]);
}
for(int i=l;i<=r;i++)tong[a[i]]=0;
}else
{
int res=ans[belong[l]+1][belong[r]-1];
for(int i=l;i<=en[belong[l]];i++)
{
if(!tong[a[i]]&&a[i]!=res)
{
tong[a[i]]+=b[a[i]]*(cnt[belong[r]-1][a[i]]-cnt[belong[l]][a[i]]);
}
tong[a[i]]+=b[a[i]];
Ans=max(tong[a[i]],Ans);
}
for(int i=st[belong[r]];i<=r;i++)
{
if(!tong[a[i]]&&a[i]!=res)
{
tong[a[i]]+=b[a[i]]*(cnt[belong[r]-1][a[i]]-cnt[belong[l]][a[i]]);
}
tong[a[i]]+=b[a[i]];
Ans=max(tong[a[i]],Ans);
}
Ans=max(Ans,(tong[res]+(cnt[belong[r]-1][res]-cnt[belong[l]][res])*b[res]));
for(int i=l;i<=en[belong[l]];i++)tong[a[i]]=0;
for(int i=st[belong[r]];i<=r;i++)tong[a[i]]=0;
}
return Ans;
}
int main()
{
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
// freopen("lsyj_ex.in","r",stdin);
// freopen("a.in","r",stdin);
// freopen("a.out","w",stdout);
cin>>n>>q;
for(int i=1;i<=n;i++)
{
cin>>a[i];
if(!mp[a[i]])
{
mp[a[i]]=++tot;
b[tot]=a[i];
}
a[i]=mp[a[i]];
}
// for(int i=1;i<=n;i++)
// {
// cout<<a[i]<<" ";
// }
// cout<<endl;
int l,r;
init();
for(int i=1;i<=q;i++)
{
cin>>l>>r;
cout<<query(l,r)<<endl;
}
return 0;
}
/*
5 5
9 8 7 8 9
1 2
3 4
4 4
1 4
2 4
*/