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-2k]…
然後還得是迴文串 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太難了,溜了