A. Exercising Walk
void solve()
{
int a,b,c,d,a1,b1,a2,b2,na,nb;
rd(a),rd(b),rd(c),rd(d);
rd(na),rd(nb),rd(a1),rd(b1),rd(a2),rd(b2);
if(a1>a2) swap(a1,a2);
if(b1>b2) swap(b1,b2);
int dx=na+b-a;
int dy=nb+d-c;
if(min(dx,na)<a1||max(dx,na)>a2||min(dy,nb)<b1||max(dy,nb)>b2||a1==a2&&(a!=0||b!=0)||b1==b2&&(c!=0||d!=0)) puts("No");
else puts("Yes");
}
dx是x方向上的位移,dy是y方向上的位移,
判断一下位移加上初始位置是否超过规定的范围,
由样例可得,需要特判一下x1 == x2 || y1 == y2,
这种情况下要求你在x轴或y轴位移=路程=0,
也就是不允许反复横跳
B. Composite Coloring
n<=1000,
第11个质数312=961
第12个质数322=1024
所以至多用11种颜色(其实题目说了)
然后上色就行了
const int maxn=1e3+10;
int n,a[maxn],ans[maxn],color[]={2,3,5,7,11,13,17,19,23,29,31};
void solve()
{
rd(n);
int c=0;
map<int,int>m;
for(int i=1;i<=n;i++) rd(a[i]);
for(int i=1;i<=n;i++)
{
for(int j=0;j<=11;j++)
{
if(a[i]%color[j]==0)
{
if(m[j]==0)
{
ans[i]=++c;
m[j]=c;
}
else
ans[i]=m[j];
break;
}
}
}
cout<<c<<endl;
for(int i=1;i<=n;i++) cout<<ans[i]<<' ';
cout<<endl;
}
C. K-Complete Word
题目链接
分循环奇数次和偶数次两种情况,
证得要想使s为回文串,
每个循环节也得是回文串。
既然有循环节,很自然会想到分组,
就是将每一个循环节的第i位分成一组,
每一组的字符我们都要将它们变成一样。
那么我们应该将它们变成什么字符,为什么?
题目要求,改变次数最少,
那么我们可以设定一个数组/map来存储
将这组数全变成某个字母的花费
显然,每一组数一共有n/k个,它的花费就是
n/k减去这个字母在这一组数里面的出现次数
因为是回文,所以第i组数与第k-1-i组数必须相同,
即我们需要将第i组和第k-1-i组数的花费加一起,选a-z中花费最小的,将花费加到答案里去,
这里要特判一下中点,也就是i= =k-1-i的时候,
多计算了一次,除以2后直接加到答案里。
int n,k;
string s;
ll ans;
void solve()
{
rd(n),rd(k);
cin>>s;
ans=0;
for(int i=0;i<=(k-1)/2;i++)
{
map<char,int>m;
for(int j=i,p=k-1-j;j<n&&p<n;j+=k,p+=k) m[s[j]]++,m[s[p]]++;
for(char j='a';j<='z';j++) m[j]=2*n/k-m[j];
int minn=inf;
for(char j='a';j<='z';j++) minn=min(m[j],minn);
if(i==k-1-i) ans+=minn/2;
else ans+=minn;
}
cout<<ans<<endl;
}
D. Walk on Matrix
题目链接
Bob是一个没有学好dp的学生,
他从起点开始贪心到终点,每一步取到最大值.
学过最基本dp问题(数塔)的人都知道,
dp应该是从最后一步去反推上去
因为你目前这一步拿到最大值,
不代表你最后能拿到最大值,
说不定你这个最大值后面的数特别特别小。
利用这个概念,我们可以构造一个3*3的矩阵,
使他的错误答案为0,正确答案为n。
那么怎么构造呢?
(1,3),(3,1),(3,3)填n,
(2,2)填100000(217的二进制数)
其余位置填11111(218-1的二进制数)
为什么这么填?
因为他是正向来贪心的,
如果aij是一个比与他左边和上面两个数都大的并且每一位全为1的二进制数,左边和上面的数分别为n和100000000(一个远大于n的数并且除了最高位,每一位都是0的二进制数),他会选择100000000,而不是n,所以我们在(3,3)位置放n,
(3,2),(2,3)位置我们让他错误的结果计算出来都是100000000,正确的结果为n,即可
题目要求是1e5,所以取217和218-1
二进制答案(重复0省略,1省略)
void solve()
{
rd(n);
cout<<"3 3"<<endl;
cout<<"262143 262143 "<<n<<endl;
cout<<"262143 131072 262143"<<endl;
cout<<n<<" 262143 "<<n<<endl;
}