ABC 略
D
n个数互质,即n个数都是质数,预处理前4e5个质数,原排列从大到小排序求前缀和,质数求前缀和,从后往前循环第一个前者前缀和能大于等于后者就是留下的i个数。
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=4e5+2;
int T,n,a[N],s[N],sum[N],prime[N],cnt;
bool v[58001100];
void init()
{
}
void solve()
{
cin>>n;
init();
for(int i=1;i<=n;i++)
cin>>a[i];
sort(a+1,a+n+1);
reverse(a+1,a+n+1);
for(int i=1;i<=n;i++)
s[i]=s[i-1]+a[i];
for(int i=n;i>=0;i--)
if(s[i]>=sum[i]) {cout<<n-i<<endl; break;}
}
signed main()
{
for(int i=2;i<=5800100;i++)
{
if(v[i]) continue;
prime[++cnt]=i;
for(int j=i;j<=5800100/i;j++) v[i*j]=1;
}
for(int i=1;i<=4e5;i++)
sum[i]=sum[i-1]+prime[i];
std::ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>T;
while(T--) solve();
}
E
n*k预处理出s中第i个字符下一个字符j的位置用f[i][j]表示,如果没有就是n+1。此后的每个t都可以O(lengeh(t))得到t匹配的最后一位的位置。先利用刚刚的f预处理出每个位置的之前k种字母的最近位置,然后利用bfs算出每个位置跳到n+1的最短距离。
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=1e6+2;
int T,n,k,Q,f[N][27],d[N];
string c,t;
vector<int> g[N];
queue<int> q;
void init()
{
for(int i=1;i<=n;i++)
d[i]=0x3f3f3f3f3f3f;
d[n+1]=0;
}
void solve()
{
cin>>n>>k;
init();
for(int i=1;i<=n;i++)
cin>>c[i];
for(int i=n;i>=0;i--)
{
if(i==n)
{
for(int j=1;j<=k;j++)
f[i][j]=n+1;
}
else
{
for(int j=1;j<=k;j++)
f[i][j]=f[i+1][j];
f[i][c[i+1]-'a'+1]=i+1;
}
}
for(int i=0;i<=n+1;i++)
for(int j=1;j<=k;j++)
{
g[f[i][j]].push_back(i);
}
q.push(n+1);
while(q.size())
{
int x=q.front();q.pop();
for(int i=0;i<g[x].size();i++)
{
if(d[g[x][i]]>d[x]+1)
{
d[g[x][i]]=d[x]+1;
q.push(g[x][i]);
}
}
}
cin>>Q;
while(Q--)
{
cin>>t;
int p=0;
for(int i=0;i<t.length();i++)
{
if(p==n+1) break;
p=f[p][t[i]-'a'+1];
}
cout<<d[p]<<endl;
}
}
signed main()
{
std::ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
//cin>>T;
T=1;
while(T--) solve();
}