2019CSP-S模拟赛十联测day4
70+30+0=100 (rk=63)
题目
A. 罗
这题考场上想到了正解,但是没调出来啊,难受,最后交了一发带着错误的竟然还多过了第9个点,第二天早上发现了傻逼错误,匹配时候 相等且不等于问号 才有贡献,忘了判不等于问号。。。
- 首先发现的是 * 不会很多,其次发现它最多就只有一个,因为一个 * 就已经能解决所有问题
- 什么时候没有 * 呢 ?,当且仅当两个串的长度相等且都不包含 * ,这时就一位一位匹配,相等且不等于问号的位置就填那个字符,否则填问号
- 其他情况我们已经确定有且仅有一个 * ,那么长度怎么确定?由于题目要求长度最长,我们最长只能长到,两个串中非 * 个数中较小的那个长度加一,加的是那个 *,那么我们长度也确定了
- 下一个要求,问号数最少,我们考虑 * 放在什么位置可以使确定的字符最多,即问号最少,我们把两串从头起匹配(按照上述的原则),尾起匹配,枚举断点(即 * 的位置),选一个确认位最多且最靠前的即可,如果匹配途中遇到 *,说明接下来一连串都不能确定,break 掉即可
B. 小
- 这题有个结论,我不知道怎么证明,以后记住就好了,一个不超过的数的质因子个数最多是级别
- 我们对于每一个质因子考虑它能构成的最长符合题意的区间,如果我们把所有包含某个质因子的位置都丢进一个数组里面,如果存在那么我们就可以得到一个长度为
的区间,移项后得到,排序后这个东西可以用双指针求,那么时间是线性的,即 - 总复杂度,最后一个是排序
C. 黑
考场上瞄了一眼 好像不给分,那就不做了继续调T1。。。。
待填坑。。。
代码
A. 罗 赛后代码
#include<bits/stdc++.h>
#define FOR(i,a,b) for (register int i=(a);i<=(b);i++)
#define For(i,a,b) for (register int i=(a);i>=(b);i--)
#define mem(i,j) memset(i,j,sizeof(i))
#define GO(u) for (register int j=f[u];j!=-1;j=nxt[j])
#define pb puss_back
#define fi first
#define se second
#define MP make_pair
using namespace std;
typedef long long ll;
const int N=2e5+5;
int T,anslen,n,m,f[N],g[N];
char s1[N],s2[N],t[N],ans[N];
inline int read()
{
int x=0,f=1;
char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') {x=(x<<3)+(x<<1)+c-'0';c=getchar();}
return f*x;
}
inline void write(int x)
{
if (x<0) putchar('-'),x=-x;
if (x>9) write(x/10);
putchar(x%10+'0');
return;
}
inline void input()
{
scanf("%s",s1+1);
scanf("%s",s2+1);
n=strlen(s1+1);
m=strlen(s2+1);
return;
}
inline void output()
{
FOR(i,1,anslen) putchar(ans[i]);
putchar('\n');
return;
}
inline void Case1()
{
anslen=n;
FOR(i,1,n)
{
if (s1[i]==s2[i]) ans[i]=s1[i];
else ans[i]='?';
}
return;
}
inline void Case2()
{
int cnt1=0,cnt2=0,cnt,pos,val=0;
FOR(i,1,n) if (s1[i]!='*') cnt1++;
FOR(i,1,m) if (s2[i]!='*') cnt2++;
cnt=min(cnt1,cnt2);
anslen=cnt+1;
FOR(i,1,anslen) ans[i]='?';
FOR(i,0,max(n,m)) f[i]=g[i]=0;
pos=-1;
FOR(i,1,min(n,m))
{
if (s1[i]=='*'||s2[i]=='*') break;
if (s1[i]==s2[i]&&s1[i]!='?') f[i]++;
}
FOR(i,1,min(n,m))
{
if (s1[n-i+1]=='*'||s2[m-i+1]=='*') break;
if (s1[n-i+1]==s2[m-i+1]&&s1[n-i+1]!='?') g[i]++;
}
FOR(i,1,min(n,m)) f[i]+=f[i-1],g[i]+=g[i-1];
FOR(i,0,min(n,m))
{
int tmpval=0;
tmpval+=f[i];
tmpval+=g[min(n,m)-i];
if (tmpval>val)
{
val=tmpval;
pos=i;
}
}
FOR(i,1,pos)
{
if (s1[i]=='*'||s2[i]=='*') break;
if (s1[i]==s2[i]&&s1[i]!='?') ans[i]=s1[i];
}
FOR(i,1,anslen-pos-1)
{
if (s1[n-i+1]=='*'||s2[m-i+1]=='*') break;
if (s1[n-i+1]==s2[m-i+1]&&s1[n-i+1]!='?') ans[anslen-i+1]=s1[n-i+1];
}
ans[pos+1]='*';
// FOR(i,1,min(n,m)) printf("%d ",f[i]);printf("\n");
// FOR(i,1,min(n,m)) printf("%d ",g[i]);printf("\n");
return;
}
int main()
{
// freopen("data.in","r",stdin);
// freopen("myans.out","w",stdout);
T=read();
while (T--)
{
input();
if (n==m) Case1();
else Case2();
output();
}
return 0;
}
B. 小 赛后代码
#include<bits/stdc++.h>
#define FOR(i,a,b) for (register int i=(a);i<=(b);i++)
#define For(i,a,b) for (register int i=(a);i>=(b);i--)
#define GO(u) for (register int j=f[u];j!=-1;j=nxt[j])
#define mem(i,j) memset(i,j,sizeof(i))
#define MP make_pair
#define pb push_back
#define fi first
#define se second
using namespace std;
typedef long long ll;
const int N=5e5+5;
const int M=1e6+5;
const int P=8e4+5;
int n,a[N],ans1=0,ans2=0,mx=0;
int vis[M],pr[P],id[M];
vector <int> vec[P];
vector <pair<int,int> > Vec;
inline int read()
{
int x=0,f=1;
char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') {x=(x<<1)+(x<<3)+c-'0';c=getchar();}
return f*x;
}
inline void write(int x)
{
if (x<0) putchar('-'),x=-x;
if (x>9) write(x/10);
putchar(x%10+'0');
return;
}
inline void init()
{
FOR(i,2,mx)
{
if (!vis[i]) pr[++pr[0]]=i;
for (register int j=1;j<=pr[0]&&i*pr[j]<=mx;j++)
{
vis[i*pr[j]]=1;
if (i%pr[j]==0) break;
}
}
FOR(i,1,pr[0]) id[pr[i]]=i;
return;
}
inline void insert(int pos)
{
for (register int i=1;i<=pr[0]&&pr[i]*pr[i]<=a[pos];i++)
{
if (a[pos]%pr[i]==0) vec[i].pb(pos);
while (a[pos]%pr[i]==0) a[pos]/=pr[i];
}
if (a[pos]>1) vec[id[a[pos]]].pb(pos);
return;
}
inline void solve(int p)
{
Vec.clear();
FOR(i,0,(int)vec[p].size()-1) Vec.pb(MP(vec[p][i]-2*i,i));
sort(Vec.begin(),Vec.end());
int mn=1e9,pointer=(int)Vec.size()-1;
For(i,(int)Vec.size()-1,0)
{
while (pointer>=0&&Vec[pointer].fi+1>=Vec[i].fi) mn=min(mn,Vec[pointer].se),pointer--;
if (mn==Vec[i].se) continue;
int l=mn,r=Vec[i].se,len=2*(r-l+1);
if (len>n) ans1=1,ans2=n;
else if (len>vec[p][r]&&len>=ans2-ans1+1) ans1=1,ans2=len;
else if (len>ans2-ans1+1||(len==ans2-ans1+1&&vec[p][r]-len+1<ans1)) ans1=vec[p][r]-len+1,ans2=vec[p][r];
}
return;
}
int main()
{
n=read();
FOR(i,1,n) a[i]=read(),mx=max(mx,a[i]);
init();
FOR(i,1,n) insert(i);
FOR(i,1,pr[0]) solve(i);
write(ans1);putchar(' ');write(ans2);
// FOR(i,0,(int)vec[2].size()-1) printf("%d ",vec[2][i]);
return 0;
}