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

A 在一個方格可以多次,那麼可以在相鄰的兩個方格來回走,然後會在左右或者的一個方向剩下幾步,判斷是否越邊界就可以了,除此之外還要特判x1== x2或者y1== y2(剛纔那樣有一個前提條件,那個方向上得能邁出去,感謝樣例)

#include<bits/stdc++.h>
using namespace std;
const int N=100010;
typedef long long ll;
int t,a,b,c,d,x,y,x1,x2,y1,y2;
int main()
{
	cin>>t;
	while(t--)
	{
		cin>>a>>b>>c>>d>>x>>y>>x1>>y1>>x2>>y2;
		if(x==x1&&x1==x2&&(a||b))
		{
			puts("No");
			continue;
		}
		if(y==y1&&y==y2&&(c||d))
		{
			puts("No");
			continue;
		}
		if(a>=b) a=a-b,b=0;
		else b=b-a,a=0;
		if(c>=d) c=c-d,d=0;
		else d=d-c,c=0;
		if(x-x1>=a&&x2-x>=b&&y-y1>=c&&y2-y>=d) puts("Yes");
		else puts("No"); 
	}
	
	return 0;
  }  

B 相同顏色的數的gcd必須大於1,那麼我們可以給有形同質因子的數全部染上相同的顏色,然後就分解質因子唄,第11個質因子是31,31*37>1000了,所以前11個質質數完全可以處理1000以內的所有合數。給每個出現的質數一個顏色,每個合數中選一個質因數染色

#include<bits/stdc++.h>
using namespace std;
const int N=100010;
typedef long long ll;
int t,n;
int a[N],c[N];
int main()
{
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d",&n);
		int num[10000]={0},m=1;//num標記質因數的顏色
		for(int i=1;i<=n;i++) 
		{
			scanf("%d",a+i);
			for(int j=2;j*j<=a[i];j++)//分解質因數
			{
				if(a[i]%j==0) 
				{
					if(num[j]) c[i]=num[j];
					else c[i]=num[j]=m++;
					break;
				}
				while(a[i]%j==0) a[i]/=j;
			}
		}
		printf("%d\n",m-1);
		for(int i=1;i<=n;i++) printf("%d ",c[i]);
		puts("");
	}
	return 0;
  }  

C 根據定義si=s[k+i],那麼就有
s1=s[1+k]=s[1+2k]…
sn=s[n-k]=s[n-2
k]…
然後還得是迴文串 s1=sn,聯立一下這些位置必須相等,找最多的字母次數,總的這些位置的數量減它就是這些位置的最小變化,其他位置一樣,k是奇數還需要特判一下。

#include<bits/stdc++.h>
using namespace std;
const int N=200010;
typedef long long ll;
int t,n,k;
int a[N],c[N];
char s[N];
int main()
{
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d %d ",&n,&k);
		scanf("%s",s+1);
		int ans=0;
		for(int i=1;i<=(k+1)/2;i++)
		{
			int num[30]={0};//別忘了清0
			if((k&1)&&i==(k+1)/2)//這個時候的i和k-i+1相等,所以得特判
				for(int j=i;j<=n;j+=k) num[s[j]-'a']++;
			 else 
			 {
			 	for(int j=i;j<=n;j+=k) num[s[j]-'a']++;
			 	for(int j=k-i+1;j<=n;j+=k) num[s[j]-'a']++;
			 }
			 int sum=0,m=0;
			 for(int i=0;i<26;i++) m=max(num[i],m),sum+=num[i]; 
			 ans+=(sum-m);
		}
		printf("%d\n",ans);
	}
	return 0;
  }  

D 他的錯誤dp是因爲&過程中的最大值不一定能使後面的&操作最大
要使最優解與他輸出的差值爲k,感覺兩個值分別等 k和0是比較好構造吧,所以我的目的是使最優解爲k,而dp輸出0,假設點[n,m]位置爲k,爲方便構造減少分支情況就把所有情況都從一個方向來,就令[n-1,m]爲0,這個方向一定爲0。
接下來就是使 dp[n][m-1]&k 等0,而[n,m-1]可以得到的較小的值&k等k,什麼值&k等0呢,k按位取反(令他爲m)。
然後看一下m的範圍是3e5是不是一定比1e5範圍的k大,3e5以內的數二進制最多有19位,而1e5以內最多有17位,所以k的18位上一定是0,那麼m的18位就一定是1了,所以m一定大於k 。
所以就可構造[n-1,m-1]爲m,[n,m-2]爲k,令s=2^18-1(二進制下各位都是1,小於3e5的最大值,&任何數的結果都等原數),其他位所有數都爲s,這樣兩行三列足矣,所以構造的矩陣就是 s m 0
k s k

#include<bits/stdc++.h>
using namespace std;
const int N=200010;
typedef long long ll;
int t,n,k,m,s;
int a[N],c[N];
char s[N];
int main()
{
		cin>>k;
		for(int i=0;i<20&&(m+(1<<i)<3e5);i++)
		{
			s+=(1<<i);
			if((k&(1<<i))==0&&m+(1<<i)<3e5)
				m+=(1<<i);
		}
		cout<<2<<' '<<3<<endl;
		cout<<s<<' '<<k<<' '<<0<<endl;
		cout<<m<<' '<<s<<' '<<k;
	return 0;
  }  

第一次過四題體驗挺好hh,E太難了,溜了

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