贪心,每一位取t和9-t中较小的。注意首位不能为0。
#include <iostream>
#include <stdio.h>
#include <string>
#include <map>
#include <vector>
#include <stack>
#include <queue>
#include <string.h>
#include <algorithm>
#include <math.h>
using namespace std;
char num[22];
int main(){
scanf("%s",num);
int len=strlen(num);
for(int i=0;i<len;i++){
int t=num[i]-'0';
t=min(t,9-t);
if(i==0&&t==0)t=9;
printf("%d",t);
}
return 0;
}
B Han Solo and Lazer Gun
首先,把x0,y0平移到原点。然后所有的x和y也跟着平移。判断的时候,暴力扫一遍,如果两个点的交叉乘积相等,它们的连线肯定过原点。
#include <iostream>
#include <stdio.h>
#include <string>
#include <map>
#include <vector>
#include <stack>
#include <queue>
#include <string.h>
#include <algorithm>
#include <math.h>
using namespace std;
int x[1010];
int y[1010];
bool flag[1010];
int main(){
int n;
cin>>n>>x[0]>>y[0];
for(int i=1;i<=n;i++){
cin>>x[i]>>y[i];
x[i]-=x[0];
y[i]-=y[0];
}
int ans=0;
for(int i=1;i<=n;i++){
if(flag[i])continue;
ans++;
flag[i]=1;
for(int j=i+1;j<=n;j++){
if(x[i]*y[j]==x[j]*y[i])flag[j]=1;
}
}
cout<<ans<<endl;
return 0;
}
C Watto and Mechanism
在字典树上dfs。因为整个串只会出现abc三种字符,所以在每个节点,尝试沿着三条不同的路径往下走,注意和原串不同的路径只能走一次且必须走一次。详见代码注释。
#include <iostream>
#include <stdio.h>
#include <string>
#include <map>
#include <vector>
#include <stack>
#include <queue>
#include <string.h>
#include <algorithm>
#include <math.h>
using namespace std;
struct node{
int next[3];
bool flag; //flag=1表示是串结尾
}Trie[600010];
char tmp[600010];
//k为串的位置,index为字典树中节点位置
bool dfs(int k,int index,bool diff){
if(k!=0&&index==0)return 0; //找不到
if(tmp[k]=='\0'){ //串的结尾
if(Trie[index].flag&&diff) return 1; //字典树中也遇到结尾,且恰有一个字符不同
else return 0;
}
bool f=Trie[index].flag;
for(int i=0;i<3;i++){
if(i+'a'==tmp[k]){ //与串的字符相同
if(dfs(k+1,Trie[index].next[i],diff))return 1;
}else{
if(!diff){ //与串的字符不同,若之前没出现过不同,则可以继续搜索
if(dfs(k+1,Trie[index].next[i],1))return 1;
}
}
}
return 0;
}
int main(){
int n,m;
cin>>n>>m;
int pos=0;
for(int i=1;i<=n;i++){
scanf("%s",tmp);
int len=strlen(tmp);
int cur=0;
for(int j=0;j<len;j++){
int next=Trie[cur].next[tmp[j]-'a'];
if(next==0){
next=++pos;
Trie[cur].next[tmp[j]-'a']=next;
}
if(j==len-1){
Trie[next].flag=1;
}
cur=next;
}
}
for(int i=1;i<=m;i++){
scanf("%s",tmp);
if(dfs(0,0,0)){
printf("YES\n");
}else{
printf("NO\n");
}
}
return 0;
}
D R2D2 and Droid Army
注意到m非常小,我们可以用two pointers+spare table来解决。我们对每个特性都开一个spare table,就可以迅速查询该特性区间内的最大值。然后用two pointers扫一遍解决。
two pointers扫一遍解决。
#include <iostream>
#include <stdio.h>
#include <string>
#include <map>
#include <vector>
#include <stack>
#include <queue>
#include <string.h>
#include <algorithm>
#include <math.h>
using namespace std;
const int maxn=100010;
int a[5][maxn][18];
int pow2n[18];
int ans[5];
int tmp[5];
int query_max(int mec,int l,int r){
int d=r-l+1;
int k=-1;
while(d){
k++;
d>>=1;
}
return max(a[mec][l][k],a[mec][r-(1<<k)+1][k]);
}
int main(){
pow2n[0]=1;
for(int i=1;i<18;i++)pow2n[i]=pow2n[i-1]<<1;
int n,m,k;
cin>>n>>m>>k;
for(int i=1;i<=n;i++){
for(int j=0;j<m;j++){
scanf("%d",&a[j][i][0]);
}
}
for(int i=0;i<m;i++){
for(int j=1;pow2n[j]<=n;j++){
for(int k=1;k+pow2n[j-1]<=n;k++){
a[i][k][j]=max(a[i][k][j-1],a[i][k+pow2n[j-1]][j-1]);
}
}
}
int L=1;
int R=1;
int MAX=0;
while(R<=n){
int sum=0;
for(int i=0;i<m;i++){
tmp[i]=query_max(i,L,R);
sum+=tmp[i];
}
if(sum>k){
L++;
if(R<L)R++;
}else{
if(R-L+1>MAX){
MAX=R-L+1;
memcpy(ans,tmp,sizeof(ans));
}
R++;
}
}
for(int i=0;i<m;i++){
printf("%d ",ans[i]);
}
return 0;
}