题目地址
给出每个数字需要的笔画数,给出总的笔画数求问可以组成的最大数字
优先考虑数字的数量 在数量相同的时候找数最大的
很容易发现,1是两画中最大的,7是三画中最大的
所以n为偶数直接全为1可以保证数字数量最多,n为奇数先抽出3创造一个7再全变成1保证结果最大
void solve()
{
int n=read();
if(n%2==0)
{
n/=2;
rep(i,1,n)
{
printf("1");
}
cout<<'\n';
}
else
{
printf("7");
n-=3;
n/=2;
rep(i,1,n)
{
printf("1");
}
printf("\n");
}
}
大概意思是给出一个字符串,你可以无限加倍一直延伸下去,
对于它的每个前缀中0的数目减去1的数目
等于x 共有多少个这样的前缀
若有无限个则输出-1
我们先开一个num数组来记录当前出现的0和1的数目之差
无限
在这种情况下,肯定是每一串都对后面的没有造成影响,所以原字符串中0和1的数目要保证一样来相互抵消,所以num[len]应该要等于0
然后我们寻找在这个字符串中是否出现过满足x的位置 是则无限,反之就是0
if(num[n]==0)
{
bool flag=true;
for(int i=1;i<=n&&flag;i++)
if(num[i]==k)
flag=false;
if(!flag)
{
puts("-1");
return ;
}
else
{
puts("0");
}
}
有限
有限的话我们假设在经历了n个循环后在n+1个循环找到了满足条件的位置,我们只需要统计位置的个数就好了
注意: 如果为0,那要先加1,题目要求空串也算
假设当前位置可以满足条件且已经经历过n个循环,那么
n*num[len]+num[pos]==x
所以我们遍历原字符串,当目前位置满足以下条件时
(x-num[pos])%num[len]==0
可满足
但是! 我们要考虑负数的情况,因为1%(-1)也为0,但是方向不同,不断远离不可能到达,所以要排除,我们在后面需要再加一个条件来判断符号是否相同
if((k-num[i])%num[n]==0&&(k-num[i])/num[n]>=0)
改成这样就好了
所以代码是
void solve()
{
ms(num,0);
n=read(),k=read();
scanf("%s",str+1);
rep(i,1,n)
{
if(str[i]=='0')
{
num[i]=num[i-1]+1;
}
else
{
num[i]=num[i-1]-1;
}
}
if(num[n]==0)
{
bool flag=true;
for(int i=1;i<=n&&flag;i++)
if(num[i]==k)
flag=false;
if(!flag)
{
puts("-1");
return ;
}
else
{
puts("0");
}
}
else
{
int ans=0;
if(k==0){ans++;}
rep(i,1,n)
{
if((k-num[i])%num[n]==0&&(k-num[i])/num[n]>=0)///要求同号
ans++;
}
cout<<ans<<endl;
}
}
给出一个模式串和目标串
从一个空串开始逐步变成目标串
每次可以选取模式串的子串排在空串后面,顺序不能变
求最小的次数
思路很明显,每一次遍历都找尽量长的子串,但是暴力找的话
1e5范围n2直接炸了…
比如这样
int cnt=1;
int st=0;
len=tmp.size();
int len1=ans.size(),pos=0;
while(pos<len1)
{
bool flag=false;
for(st=0;st<=len-1&pos<len1;st++)
{
if(tmp[st]==ans[pos])
pos++,flag=true;
}
if(pos!=len1)
cnt++;
if(!flag)
{
cout<<-1<<endl;
return ;
}
}
cout<<cnt<<endl;
暴力查找肯定不行,我们可以优化for循环内部的那个循环,我们开个vector数组储存原字符串中每种字母的所有下标,比如
vector<int>v[27];
rep(i,0,len-1)
{
int pos=tmp[i]-'a'+1;
v[pos].pb(i);
}
利用STL库的upper_bound二分查找第一个符合条件的下标,找到后再更新下标
注意upper和lower这两个的区别
pos=upper_bound(v[id].begin(),v[id].end(),pos)-v[id].begin();
pos=v[id][pos];
每次没找到就从头再开始就好了并ans++
代码是
string tmp,ans;
void solve()
{
cin>>tmp>>ans;
int len=tmp.size();
vector<int>v[27];
rep(i,0,len-1)
{
int pos=tmp[i]-'a'+1;
v[pos].pb(i);
}
int cnt=1,pos=-1;
len=ans.size();
rep(i,0,len-1)
{
int id=ans[i]-'a'+1;
int num=v[id].size();
if(num==0)
{
puts("-1");
return ;
}
if(pos>=v[id][num-1])
{
pos=-1;
cnt++;
i--;
continue;
}
pos=upper_bound(v[id].begin(),v[id].end(),pos)-v[id].begin();
pos=v[id][pos];
//cout<<pos<<endl;
}
cout<<cnt<<endl;
}