题意:
输出n+1个字符串,si和si+1的公共前缀长为ai
思路:
我们只要模拟过程即可,只要两个字母就可以输出任意多个满足题意的字符串。
我们只要改,第一个不相同的就好,后面的都输出一样的,但是一定要确保长度能够达到和下一个字符串相等的长度
思路好想,但是写的过程错了很多小细节,暴露代码能力
AC代码:
#include
using namespace std;
#define mod 1e9+7
#define N 100
#define inf 0x3f3f3f3f
const double PI = atan(1.0)*4.0;
typedef long long ll;
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
// freopen("E:\\in.txt","r",stdin);
int k;
cin>>k;
while(k--)
{ char a[105][105];int b[105];
int n;
cin>>n;
for(int i=1;i<=n;i++)
cin>>b[i];
b[n+1]=50;
for(int i=1;i<=b[1]+1;i++)
a[1][i]='b';
for(int i=2;i<=n+1;i++)
{ int j;
for( j=1;j<=b[i-1];j++)
{
a[i][j]=a[i-1][j];
}
if(a[i-1][j]=='a')a[i][j]='b';
else a[i][j]='a';
for(j++;j<=max(b[i]+1,b[i-1]+1);j++)
{
a[i][j]='a';
}
}
for(int i=1;i<=n+1;i++)
{
for(int j=1;j<=max(b[i]+1,b[i-1]+1);j++)
cout<<a[i][j];
cout<<endl;
}
}
}
题意:
有 n 片海域,每片海域有一个初始深度,每 2 * k秒,前 k秒 每秒深度 +1 ,后 k 秒每秒深度 -1 .有一个人想从海岸一边游到另一边 ,每秒它可以移动到下一片海域或者停留在当前海域,如果当前海域深度大于 l 他会被淹死,问他可不可以游到对岸。
思路:
这道题可以通过dp来做。
状态表示:f[i][j] //当这个人到达第i片海域的时间为j秒这个状态是否合法
状态计算:f[i][j]可以由两个状态转移得到
f[i][j-1] //上一秒在第i片海域选择不移动
f[i-1][j-1] //上一秒在第i-1片海域选择向右移动
只要两者有一个状态是合法的,那么f[i][j]就是可到达的。
然后我们还要证明f[i][j]状态本身是否合法,即在第j秒时海域i的深度是否大于l。
最后我们只需要找找f[n][j]的状态中是否有合法的即可,如果f[n][j]状态中有合法的,那么最终的结果就是Yes.
#include
#define LL long long
#define PII pair
using namespace std;
const int N=1e2+5,M=2e4+5;
int a[N],p[2*N];
int f[N][M];
void init(int k)
{
for(int i=0;i<=k;i++) p[i]=i; //预处理出涨潮的情况
for(int i=1;i<k;i++) p[k+i]=k-i;
for(int i=0;i<2*k;i++) f[0][i]=1; //设置起点,进去的时间区间在[0,2k]内即可
}
int main()
{
int t;
cin>>t;
while(t--)
{
memset(f,0,sizeof f);
int n,k,l;
cin>>n>>k>>l;
for(int i=1;i<=n;i++)
cin>>a[i];
init(k);
for(int i=1;i<=n;i++) //枚举海域
for(int j=0;j<2*k*n;j++) //枚举时间
{
f[i][j]=max(f[i][j-1],f[i-1][j-1]); //计算状态f[i][j]是否可到达
if(l<p[j%(2*k)]+a[i]) f[i][j]=0; //计算f[i][j]本身是否合法
}
bool ok=false;
for(int i=0;i<2*k*n;i++)
if(f[n][i]) ok=true;
if(ok) puts("Yes");
else puts("No");
}
return 0;
}
#include
using namespace std;
const int N=3e5+5;
int a[N];
void solve()
{
int n,k,l,i;
scanf("%d%d%d",&n,&k,&l);
a[0]=a[n+1]=k+1;
for(i=1; i<=n; i++)
scanf("%d",&a[i]),
a[i]=l-a[i];//a数组存放上涨a[i]后依然能通过
int w=k+1,f=-1;//w表示当前潮汐高度f表示下一秒潮汐变化的数字
for(i=1; i<=n; i++)
{
if(a[i]<0)
{
printf("No\n"); //无法通过
return;
}
else if(a[i]>=k)
w=k+1,f=-1;//若潮汐在最高处时这个点还是安全的,可以在这个点等到潮最高时
else if(f==-1)
w=min(w+f,a[i]);//只要当前是潮落的状态就可以等待
else
{
w+=f; //若是涨潮状态这个点已经不安全了则说明这个点无法通过
if(w>a[i])
{
printf("No\n");
return;
}
}
if(w==0)
f=1;
}
printf("Yes\n");
}
int main()
{
freopen("E:\\in.txt","r",stdin);
int T;
scanf("%d",&T);
while(T--)
solve();
return 0;
}
题意:
在相对应的位置,只要 a 串上的字母大于 b 串上的字母,那么无解,否则一定有解。
要找到最小的步数,其实最大步数也就20吧。
我们首先从小的开始选择字母,对于选定的字母,我们可以把它变成什么呢?选择的字母都有其要变成的值,我们让他们都变成要变成字母里的最小的一个,比如:aaa–>cdg,那么选择的字母是 ′a′,把它变成 ′c′,然后把其都变成 ′c′。
具体实现使用 set 来维护的,每个字母维护一个 set,从小到大枚举,然后每次取当前字母要变换到的最小字母,操作次数++,然后将这些字母变成最小字母,其对应的操作就是把其余的放入到最小字母的那个set里。
复杂度 O(n∗log20)
#include
using namespace std;
const int man = 2e5+10;
#define ll long long
const ll mod = 1e9+7;
char s1[man],s2[man];
int main() {
int t;cin >> t;
while(t--){
int n;cin >> n;
scanf("%s%s",s1+1,s2+1);
bool f = 1;
for(int i = 1;i <= n;++i){
if(s1[i]>s2[i]){
f = 0;
break;
}
}
if(!f){
cout <<"-1\n";
continue;
}
int ans = 0;
set<int>s[25];
for(int i = 1;i <= n;++i){
if(s1[i]!=s2[i]){//只把不同的放入
s[s1[i]-'a'].insert(s2[i]-'a');
}
}
for(int i = 0;i < 20;++i){
if(s[i].size()==0)continue;
int minn = *s[i].begin();
s[i].erase(minn);
ans++;
for(auto it:s[i]){
s[minn].insert(it);
}
}
printf("%d\n",ans);
}
return 0;
}
题意:
有 n 个数,Koa 和另一个人比赛,每个数只能拿一次,两个人手上的值都是 0 ,使得每拿一个数都与自己手上的数进行异或,自己手上的数变成当前异或值,最后谁手上的书最大谁获胜
从决定位也就是最高位入手,由高位往低位分析。
我们设当前位为1的数字个数为x,0为y。
如果x为偶数,则无论怎么选,最后两个得分在这个位都是一样的
如果x为奇数,且x % 4 == 1,则先手的得分在该位一定是1,后手一定为0;如果x % 4 == 3, 且 y % 2 == 0,则后手完全可以跟随先手的操作,最后先手在该位一定是偶数个1,异或结果为0,先手输。如果x%4 == 3,且y % 2 == 1,那么先手一定能赢,因为先手可以一上来拿该位为0的数,使得整个局势转移到上一中情形。
#include
using namespace std;
typedef long long ll;
const ll mod = 1e9 + 7;
const int maxn = 2e6;
const int inf = 0x3f3f3f3f;
int bit[40];
int main()
{
int t; cin >> t;
while(t--)
{
int n; cin >> n;
memset(bit, 0,sizeof(bit));
for(int i = 1; i <= n; i++)
{
ll z; cin >> z;
for(int j = 0; j <= 32; j++)
if(z & (1ll << j))
bit[j]++;
}
int flag = 0;
for(int i = 32; i >= 0; i--)
if(bit[i] & 1)
{
int x = bit[i], y = n - bit[i];
if(x % 4 == 1) flag = 1;
else
{
if(y % 2 == 0) flag = -1;
else flag = 1;
}
break;
}
if(flag == 1) cout << "WIN" << endl;
else if(flag == -1) cout << "LOSE" << endl;
else cout << "DRAW" << endl;
}
}