如果满足要求,当且仅当:
① S S S的长度比 T T T正好大1;
②除去 S S S的最后一位,其他与 T T T完全相同。
直接模拟即可。
#include
#define int long long
using namespace std;
string s1,s2;
signed main()
{
cin>>s1>>s2;
if (s2.substr(0,s1.size())==s1&&s1.size()+1==s2.size()) cout<<"Yes"<<endl;
else cout<<"No"<<endl;
return 0;
}
简单贪心题,注意必须取 K K K张牌,不能少取。
然后贪心地取即可。即,先尽可能地取写有 1 1 1的牌,再尽可能地取写有 0 0 0的牌,最后取写有 − 1 -1 −1的牌。
#include
#define int long long
using namespace std;
int a,b,c,n,ans=0;
signed main()
{
cin>>a>>b>>c>>n;
int pick1=min(a,n);
ans+=pick1;
n-=pick1;
int pick2=min(b,n);
n-=pick2;
int pick3=min(c,n);
ans-=pick3;
cout<<ans<<endl;
return 0;
}
直接 01 01 01枚举暴力即可。
时间复杂度小于 O ( 2 n × n ) O(2^n×n) O(2n×n),不会超时。
#include
#define int long long
using namespace std;
int n,m,x,ans=1e9+7;
int c[105],a[105][105],pos[105];
signed main()
{
cin>>n>>m>>x;
for (int i=1;i<=n;i++)
{
cin>>c[i];
for (int j=1;j<=m;j++) cin>>a[i][j];
}
while (pos[0]==0)
{
int in[105]={0},money=0;
for (int i=1;i<=n;i++)
{
if (pos[i]==1)
{
money+=c[i];
for (int j=1;j<=m;j++) in[j]+=a[i][j];
}
}
int flag=1;
for (int i=1;i<=m;i++)
{
if (in[i]<x)
{
flag=0;
break;
}
}
if (flag==1) ans=min(ans,money);
for (int i=n;i>=0;i--)
{
if (pos[i]==1) pos[i]=0;
else
{
pos[i]=1;
break;
}
}
}
if (ans!=1e9+7) cout<<ans<<endl;
else cout<<-1<<endl;
return 0;
}
发现这是一个简单的周期问题。
但是,注意循环不一定是纯循环,极有可能为混循环。所以,我们需要开一个数组,记录下上一次到该点的时间,这样在下一次到达该地点的时候就能知道周期开始的地点与周期的循环节长度。
然后把巨大的 K K K模一下,查一查表就可以啦。时间复杂度 O ( N ) O(N) O(N)。
#include
#define int long long
using namespace std;
int n,m,x,ans=1e9+7;
int c[105],a[105][105],pos[105];
signed main()
{
cin>>n>>m>>x;
for (int i=1;i<=n;i++)
{
cin>>c[i];
for (int j=1;j<=m;j++) cin>>a[i][j];
}
while (pos[0]==0)
{
int in[105]={0},money=0;
for (int i=1;i<=n;i++)
{
if (pos[i]==1)
{
money+=c[i];
for (int j=1;j<=m;j++) in[j]+=a[i][j];
}
}
int flag=1;
for (int i=1;i<=m;i++)
{
if (in[i]<x)
{
flag=0;
break;
}
}
if (flag==1) ans=min(ans,money);
for (int i=n;i>=0;i--)
{
if (pos[i]==1) pos[i]=0;
else
{
pos[i]=1;
break;
}
}
}
if (ans!=1e9+7) cout<<ans<<endl;
else cout<<-1<<endl;
return 0;
}
比赛的时候脑子真的坏掉了,这么简单的数学题都TM没做出来。我真的太菜了。
考虑分块!
即,对于每一个块均含有至少一个砖头,且该块内所有砖头的颜色相同。任何两个相邻块的颜色均不同。
设分为了 t t t个块,那么就存在 ( n − 1 ) − ( t − 1 ) = n − t (n-1)-(t-1)=n-t (n−1)−(t−1)=n−t个相邻且颜色相同的砖头对。
根据题意,得 n − t ≤ k n-t≤k n−t≤k,即 t ≥ n − k t≥n-k t≥n−k;而每个块必须为非空,那么就必有 n − k ≤ t ≤ n n-k≤t≤n n−k≤t≤n。那么,我们就可以枚举 k k k,对于每个上述的 k k k找到所有满足要求的格局的数量并累加即可。
于是,我们设 x i ( i ≤ t ) x_i(i≤t) xi(i≤t)表示分 t t t个块时地 i i i个块的砖头的数量。易得 Σ i = 1 t x i = n Σ_{i=1}^t x_i=n Σi=1txi=n。所以,通过插板法得到, x x x数组的格局的数量为 C n − 1 t − 1 C_{n-1}^{t-1} Cn−1t−1。
得到了每个块的长度,我们开始考虑每一个块的颜色。首先,第一个块可被染的颜色的数量为 m m m,再根据任何两个相邻块的颜色均不同,后面 t − 1 t-1 t−1个块可被染的颜色的数量均为 m − 1 m-1 m−1种。所以在染色这一方面,每个块染的颜色的格局共有 m × ( m − 1 ) t − 1 m×(m-1)^{t-1} m×(m−1)t−1。
所以对于一个 t t t,满足要求的砖头颜色的格局数量有 C n − 1 t − 1 × m × ( m − 1 ) t − 1 C_{n-1}^{t-1}×m×(m-1)^{t-1} Cn−1t−1×m×(m−1)t−1种。
综上所述,答案就是:
Σ t = n − k n m × C n − 1 t − 1 × ( m − 1 ) t − 1 Σ_{t=n-k}^n m×C_{n-1}^{t-1}×(m-1)^{t-1} Σt=n−knm×Cn−1t−1×(m−1)t−1
注意逆元即可。时间复杂度为 O ( k ) O(k) O(k)。
#include
#define int long long
using namespace std;
const int mod=998244353;
int n,m,k,ans=0;
int jc[200005];
int quick_power(int a,int b)
{
a%=mod;
int res=1;
for (;b;b=b>>1,a=(a*a)%mod)
{
if (b&1) res=(res*a)%mod;
}
return res%mod;
}
int ny(int a)
{
return quick_power(a,mod-2)%mod;
}
int C(int nn,int kk)
{
if (kk==0||nn==kk) return 1;
else return ((jc[nn]*ny(jc[kk]%mod))%mod*ny(jc[nn-kk]%mod))%mod;
}
signed main()
{
cin>>n>>m>>k;
jc[0]=1;
for (int i=1;i<=200000;i++) jc[i]=(jc[i-1]*i)%mod;
for (int t=n-k;t<=n;t++)
{
int first=(C((n-1)%mod,t-1)%mod),second=(m*quick_power((m-1)%mod,t-1))%mod;
ans=(ans+((first*second)%mod))%mod;
}
cout<<ans<<endl;
return 0;
}
咕咕咕~
这不是菜的问题了,这是智商的问题了。
TM第5题这么简单,分块也没有学得多差,就是没想到,自闭了。
22 22 22分钟切掉前四题有个毛用,第五题是蒟蒻与大佬的分水岭。
谁能帮帮我这个菜鸡啊~