Educational Codeforces Round 178 (Rated for Div. 2)
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();
}