吐槽一下用c++和cincout加速莫名其妙ce或re
黑子之光
累乘输出即可
#include <bits/stdc++.h>
#define ll __int64
using namespace std;
void solve()
{
int n;
ll sum=1;
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
ll x;
scanf("%d",&x);
sum*=x;
}
printf("%I64d\n",sum);
}
int main()
{
// ios::sync_with_stdio(0);
// cin.tie(0);
// cout.tie(0);
int t;
cin>>t;
while (t--)
{
solve();
}
return 0;
}
一起摇摆
遍历每一行字符串,统计期中ji和zhiyin的数量,再用前缀和维护
#include <bits/stdc++.h>
#define ll long long
using namespace std;
int sum[10005];
void solve()
{
int n,m;
scanf("%d %d",&n,&m);
for (int i=1;i<=n;i++)
{
string s;
cin>>s;
int len=s.length();
for (int j=0;j<len;j++)
{
if (s[j]=='j')
{
if (s[j+1]=='i')
sum[i]++,j+=1;
continue;
}
if (s[j]=='z')
{
if (s[j+1]=='h'&&s[j+2]=='i'&&s[j+3]=='y'&&s[j+4]=='i'&&s[j+5]=='n')
sum[i]++,j+=5;
continue;
}
}
sum[i]+=sum[i-1];
}
while (m--)
{
int l,r;
cin>>l>>r;
if (l>r)
swap(l,r);
printf("%d\n",sum[r]-sum[l-1]);
}
}
int main()
{
// ios::sync_with_stdio(0);
// cin.tie(0);
// cout.tie(0);
solve();
return 0;
}
ikun的problem
用s.find函数查找每句话(也可以手写函数判断),然后分类讨论各种情况
#include <bits/stdc++.h>
#define ll long long
using namespace std;
bool sym[15];
string pan[15];
string s;
void find(int i,int moshi)//
{
for (int j=1;j<pan[moshi].length();j++)
{
if (s[i+j]!=pan[moshi][j])
return;
}
sym[moshi]=1;
}
void solve()
{
memset(sym,0,sizeof(sym));
string name;
int t;
cin>>name>>t;
while (t--)
{
cin>>s;
int len=s.length();
for (int i=0;i<len;i++)
if (s[i]>='A'&&s[i]<='Z')
s[i]+=32;
for (int i=0;i<len;i++)
{
for (int j=1;j<=8;j++)
{
if (s[i]==pan[j][0])
find(i,j);
}
}
}
//讨论每种情况
//先讨论是ikun还是小黑子
if (sym[2])
cout<<"5\n";
else
{
if (sym[1])
{
if (sym[3]&&sym[6])
cout<<"4\n";
else
cout<<"3\n";
}
else
{
int flag=1;
for (int i=3;i<=8;i++)
{
if (i==4)
{
if (sym[i]||sym[i+1])
i=6;
else
flag=0;
}
if (!sym[i])
flag=0;
}
if (flag==0)
cout<<"2\n";
else
cout<<"1\n";
}
}
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
pan[1]="i_am_ikun";
pan[2]="i_am_xiaoheizi";
pan[3]="problem_describe";
pan[4]="problem_source";
pan[5]="problem_num";
pan[6]="code_paste";
pan[7]="solve";
pan[8]="result";
int t;
cin>>t;
while (t--)
{
solve();
}
return 0;
}
黑子的鸡脚
线性dp
dp[i][0]表示到第i个数,还没有用过小黑妹
dp[i][1]表示到第i个数,已经用过小黑妹
dp思路就是枚举到第i个数,然后查找i-k+1~i这个区间有sum个0(用前缀和预处理维护)
接下来进行状态转移:
sum==0 这个区间是满足题目条件的:
dp[i][0]=dp[i-k][0]+1;
dp[i][1]=dp[i-k][1]+1;
两种都能转移且答案+1
sum==1 这个区间可以使用小黑妹来满足条件:
dp[i][1]=dp[i-k][0]+1;
最后无论有多少0,可以让第i个数单独划分为一个区间,只需转移i-1的状态:
dp[i][0]=max(dp[i][0],dp[i-1][0]);
dp[i][1]=max(dp[i][1],dp[i-1][1]);
#include <bits/stdc++.h>
#define ll long long
using namespace std;
char ch[10005];
int dp[10005][2],sum[10005];
int main()
{
int t;
scanf("%d",&t);
while (t--)
{
memset(dp,0,sizeof(dp));
int n,k;
scanf("%d %d",&n,&k);
getchar();
scanf("%s",ch+1);
for (int i=1;i<=n;i++)
{
sum[i]=sum[i-1];
if (ch[i]=='0')
sum[i]++;
}
for(int i=k;i<=n;i++)
{
if (sum[i]-sum[i-k]==0)
{
dp[i][0]=dp[i-k][0]+1;
dp[i][1]=dp[i-k][1]+1;
}
if (sum[i]-sum[i-k]==1)
dp[i][1]=dp[i-k][0]+1;
dp[i][0]=max(dp[i][0],dp[i-1][0]);
dp[i][1]=max(dp[i][1],dp[i-1][1]);
}
printf("%d\n",max(dp[n][0],dp[n][1]));
}
return 0;
}
黑子的01串
找规律推结论,是一道构造题,但是题目要求字典序最大,所以还需要用到一点贪心的思想
首先考虑最简单的情况a=0或b=0
这种情况x只能为0
然后考虑x为1的情况 a=4 b=3
1111000这种情况只有在最中间的时候对答案又一个贡献
如果将末尾的0插入到两个1中间:
此时x=3 情况分别是1110100 1101100 1011100
要字典序最大则应为 1110100
类似的可以推出x=5 1101010
11 0101 0 中间两个01则贡献为22+1,依次可得n个01则贡献为2n+1
我们发现这是x为奇数的情况,那么接下思考x为偶数的情况
x=2 1110001
x=4 1101001
可以发现规律只需将x-1情况的第一个1移到最后一位即可
接下来思考-1的情况:
给出a,b求出x的范围
当ab都不为0 x最小为1
最大为(a+b-abs(a+b))
例如a=3,b=4
0101010 x最大为6
a=4,b=3
1010101 x最大为6
但是有一个特殊情况当a=b,x最大应该为a+b-1
所以由以上规律可以得到-1的情况
当a>=b
我们可以得出第一位一定是1
a<b
我们可以得出只有当x取最大的时候第一位才为0
根据以上规律,给出x为奇数时,只需构造出(x-1)/2个01,这个01串前面为剩余的1,后面为剩余的0
x为偶数时,只需将x-1构造出来的答案的第一位1移到最后一位
这种情况的特例:
a<b a=3,b=4时 x为最大值6时
如果按照这种构造方式:1010100 这是x=5的情况,将1移到最后一位并不是x=6的情况,所以特判一下,直接输出01串,最后输出剩余的0即可0101010
#include <bits/stdc++.h>
#define ll long long
using namespace std;
void solve()
{
int a,b,x;
scanf("%d %d %d",&a,&b,&x);
int maxn;
if (a==b)
maxn=a+b-1;
else
maxn=a+b-abs(a-b);
if (a==0||b==0)
{
if(x!=0)
puts("-1");
else
{
for (int i=1;i<=a;i++)
printf("1");
for (int i=1;i<=b;i++)
printf("0");
printf("\n");
}
return;
}
if (maxn<x||x<1)
{
puts("-1");
return;
}
if (x%2==1)
{
for (int i=1;i<=a-(x-1)/2;i++)
printf("1");
for (int i=1;i<=(x-1)/2;i++)
printf("01");
for (int i=1;i<=b-(x-1)/2;i++)
printf("0");
}
else
{
if (x==a+b-abs(a-b)&&a<b)
{
for (int i=1;i<=x/2;i++)
printf("01");
for (int i=1;i<=b-x/2;i++)
printf("0");
}
else
{
for (int i=1;i<=a-x/2;i++)
printf("1");
for (int i=1;i<=x/2-1;i++)
printf("01");
for (int i=1;i<=b-(x/2-1);i++)
printf("0");
printf("1");
}
}
printf("\n");
}
int main()
{
int t;
scanf("%d",&t);
while (t--)
{
solve();
}
return 0;
}
黑子的养鸡场
对于某一个鸡,他有ai个位置可以选,但是他会受到其它鸡(抢位置)的影响
将所有ai进行排序,优先让ai最小的选,那么第i个鸡就只剩下ai-i+1个位置可以选则(高中乘法原理)
然后每次乘都取余
a * b * c * d * e * f %mod = a * b%mod * c%mod * d%mod * e%mod
#include <bits/stdc++.h>
#define ll __int64
using namespace std;
const ll mod=998244353;
int a[105];
void solve()
{
int n;
ll sum=1;
scanf("%d",&n);
for (int i=1;i<=n;i++)
scanf("%d",&a[i]);
// cin>>a[i];
sort(a+1,a+1+n);
for (int i=1;i<=n;i++)
{
sum=(sum*(a[i]-i+1))%mod;
if (sum==0)
break;
}
printf("%I64d\n",sum);
// cout<<sum<<"\n";
}
int main()
{
int t;
scanf("%d",&t);
while (t--)
{
solve();
}
return 0;
}
黑子的展览柜
问题比较抽象,转化为一个走路问题,有一个n*n的方格,当在(x,y)位置时,只能向(x+1,y)或(x,y+1)走,并且无时无刻都应让x>=y
此时x代表大篮球的数量,y代表小篮球的数量
所以转化为了一个很经典的递推问题:
dp[i][j]=dp[i-1][j]+dp[i][j-1]
其中横坐标大于等于纵坐标
#include <bits/stdc++.h>
#define ll __int64
using namespace std;
ll dp[25][25];
void solve()
{
int n;
scanf("%d",&n);
printf("%I64d\n",dp[n][n]);
cout<<dp[n][n]<<"\n";
}
int main()
{
dp[0][0]=1;
for (int i=1;i<=20;i++)
{
dp[i][0]=1;
for (int j=1;j<=i;j++)
{
if (i-1>=j)
dp[i][j]+=dp[i-1][j];
dp[i][j]+=dp[i][j-1];
}
}
int t;
scanf("%d",&t);
while (t--)
{
solve();
}
return 0;
}