2019CSP-S模擬賽十聯測day4

2019CSP-S模擬賽十聯測day4

link

70+30+0=100 (rk=63)

題目

A. 羅

這題考場上想到了正解,但是沒調出來啊,難受,最後交了一發帶着錯誤的竟然還多過了第9個點,第二天早上發現了傻逼錯誤,匹配時候 相等且不等於問號 纔有貢獻,忘了判不等於問號。。。

  • 首先發現的是 * 不會很多,其次發現它最多就只有一個,因爲一個 * 就已經能解決所有問題
  • 什麼時候沒有 * 呢 ?,當且僅當兩個串的長度相等且都不包含 * ,這時就一位一位匹配,相等且不等於問號的位置就填那個字符,否則填問號
  • 其他情況我們已經確定有且僅有一個 * ,那麼長度怎麼確定?由於題目要求長度最長,我們最長只能長到,兩個串中非 * 個數中較小的那個長度加一,加的是那個 *,那麼我們長度也確定了
  • 下一個要求,問號數最少,我們考慮 * 放在什麼位置可以使確定的字符最多,即問號最少,我們把兩串從頭起匹配(按照上述的原則),尾起匹配,枚舉斷點(即 * 的位置),選一個確認位最多且最靠前的即可,如果匹配途中遇到 *,說明接下來一連串都不能確定,break 掉即可

B. 小

  • 這題有個結論,我不知道怎麼證明,以後記住就好了,一個不超過TT的數的質因子個數最多是O(loglogT)O(loglogT)級別
  • 我們對於每一個質因子考慮它能構成的最長符合題意的區間,如果我們把所有包含某個質因子的位置都丟進一個數組裏面,如果存在pjpi+12(ji+1)p_j-p_i+1 \leq 2( j-i+1)那麼我們就可以得到一個長度爲
    2(ji+1)2(j-i+1)的的區間,移項後得到pj2jpi2i+1p_j-2j \leq p_i-2i+1,排序後這個東西可以用雙指針求,那麼時間是線性的,即O()O(包含這個質因子的數的個數)
  • 總複雜度O(nloglogTlogn)O(nloglogTlogn),最後一個lognlogn是排序

C. 黑

考場上瞄了一眼 n!n! 好像不給分,那就不做了繼續調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;
}

C. 黑 賽後代碼

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章