1. 程式人生 > 其它 >Codeforces Round #736 (Div. 2) (A-D)

Codeforces Round #736 (Div. 2) (A-D)

A. Gregor and Cryptography

題意:

讓你選取兩個數使得n取模與這兩個數相等 ,保證n是素數並且大於5

分析:

我們知道n是素數並且大於5,那麼他一定是個奇數,所以我們直接輸出2和n-1即可。

	

B. Gregor and the Pawn Game

題意:

給出你a,b兩個陣列,然後讓你控制b陣列的1位置,他可以移動到a陣列兩種方式:

  • 當b陣列i位置是1,如果a陣列i位置是0可以一定上面,
  • 當b陣列i位置是1,如果a陣列(i-1)位置是1可以移動到(i-1)同理可以移動 (i+1)

一個位置最多存放一個,問最多幾個?

分析:

直接模擬即可,可以放就放,不可以放就跳過去,三種情況判斷,選從i位置是否為0判斷,注意標記放1的位置。

ll n;
string str, s;
map<ll, ll>mp;
void solve()
{
    mp.clear();
    cin >> n;
    cin >> str >> s;
    ll sum = 0;
    for(int i = 0; i < n; i++)
    {
        if(s[i] == '1')
        {
            if(mp[i] == 0 && str[i] == '0')
            {
                sum++;
                mp[i] = 1;
            }
            else if(i - 1 >= 0 && mp[i - 1] == 0 && str[i - 1] == '1')
            {
                sum++;
                mp[i - 1] = 1;
            }
            else if(i + 1 < n && mp[i + 1] == 0 && str[i + 1] == '1')
            {
                sum++;
                mp[i + 1] = 1;
            }
        }
    }
    cout << sum << endl;
}

C. Web of Lies

題意:

n個數,m條邊,三種操作:

  1. 新增邊u和v保證之前沒這個邊
  2. 刪除邊u和v保證之前有這個邊
  3. 查詢,最後剩幾個點,原則是如果這個點上沒連邊就做出貢獻, 連著邊把點值最小的去除,最後是都是孤點。

分析:

我們計算邊上上值小的點,因為刪點是從小往大刪,如果,這個點連著一個比他大的點,那麼它一定會被刪掉,所以我們只需要維護沒被他大點連線的數量,每次更新只需要維護是否有比他大的數出入。

ll n,m;
string str, s;
map<ll, ll>mp;
void solve()
{
    mp.clear();
    scanf("%lld%lld",&n,&m);
    ll sum=n;
    for(int i=1;i<=m;i++){
    	ll u,v;
    	scanf("%lld%lld",&u,&v);
    	if(u<v) swap(u,v);// u>v;
    	if(mp[v]==0){
    		sum--;    		
    	}
    	mp[v]++;
    }
    ll k;
    cin>>k;
    while(k--){
    	ll op;
    	scanf("%lld",&op);
    	if(op==3){
    		printf("%lld\n",sum);
    	}else if(op==1){
    		ll u,v;
    		scanf("%lld%lld",&u,&v);
    		if(u<v) swap(u,v);// u>v;
	    	if(mp[v]==0){
	    		sum--;    		
	    	}
	    	mp[v]++;
    	}else{
    		ll u,v;
    		scanf("%lld%lld",&u,&v);
    		if(u<v) swap(u,v);// u>v;
	    	if(mp[v]==1){
	    		sum++;    		
	    	}
	    	mp[v]--;
    	}
    }
}

D. Integers Have Friends

題意:

連續一段數對一個數取模之後值相等,對最大長度。

分析:

我們經過對取模後相等,得知,他們的差值一定gcd>1因為只有這樣才能取模相等,所以問題就轉化成維護區間gcd,找到最長區間gcd>1的長度。 RMQ可以維護,感興趣可以去學學。

ll gcd(ll a,ll b){
	while(b){
		ll tmp=a%b;
		a=b;
		b=tmp;
	}
	return a;
}
ll a[maxn],b[maxn],n;
ll log_n[maxn];
ll dp[maxn][33];
void LOG(){
	log_n[1]=0;
	for(int i=2;i<=n+1;i++){
		log_n[i]=log_n[i/2]+1;
	}
}
void RMQ(){
	for(int i=1;i<=n;i++){
		dp[i][0]=abs(b[i]);
	}
	for(int j=1;(1<<j)<=n;j++){
		for(int i=1;i+(1<<(j-1))<=n;i++){
			dp[i][j]= gcd(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
		}
	}
}
ll serch(ll l,ll r){
	ll k = log_n[r-l+1];
	return gcd(dp[l][k],dp[r-(1<<k)+1][k]);
}
bool check(ll x){
	if(x==1) return true;
	for(int i=1;i<=n;i++){
		ll j=i+x-1;
		if(j>n) break;
		if(serch(i+1,j)>=2) return true;
	}
	return false;
}
void solve()
{
    scanf("%lld",&n);
    for(int i=1;i<=n;i++){
    	scanf("%lld",&a[i]);
    	b[i]=abs(a[i]-a[i-1]);
    }
    LOG();
    RMQ();
    ll l=1,r=n;
    ll ans=2;
    while(l<=r){
    	ll mid=(l+r)/2;
    	if(check(mid)) {
    		ans=mid;
    		l=mid+1;
    	}
    	else r=mid-1;
    }
    cout<<ans<<endl;
 
 
}