A.夹娃娃
Solution
前缀和裸题
Code
#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
const double eps = 1e-8;
const int NINF = 0xc0c0c0c0;
const int INF = 0x3f3f3f3f;
const ll mod = 1e9 + 7;
const ll N = 1e5 + 5;
int w[N],pre[N],n,k;
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n>>k;
for(int i=1;i<=n;i++){
cin>>w[i];
pre[i]=pre[i-1]+w[i];
}
for(int i=1;i<=k;i++){
int l,r;cin>>l>>r;
cout<<pre[r]-pre[l-1]<<'\n';
}
return 0;
}B.莫的难题
Solution
容易发现
虽然答案是由构成的,但是本质是五进制的数,
分别对应
。
假设答案长度为,则
之后转换为五进制的数,对应输出即可。
下面的代码预处理了和
(长度贡献值的前缀和)。
Code
#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
const double eps = 1e-8;
const int NINF = 0xc0c0c0c0;
const int INF = 0x3f3f3f3f;
const ll mod = 1e9 + 7;
const ll N = 1e2 + 5;
ll f[20],C[N][N];
int u[6]={1,2,3,5,9};
void init(){
for(int i=0;i<=100;i++){
for(int j=0;j<=i;j++){
if(j==0 || j==i) C[i][j]=1;
else C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;
}
}
ll base=5;
for(int i=1;i<=15;i++){
f[i]=f[i-1]+base;
if(f[i]>mod) break;
base=base*5;
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
int T;cin>>T;
init();
while(T--){
ll n,m;
cin>>n>>m;
ll k=C[n][m];
int id=0;
for(int i=1;i<=13;i++) if(f[i]<k) id=i;
k-=f[id]+1;
ll t=k;
int a[15]={0},cnt=0;
while(t>0){
a[++cnt]=t%5;
t/=5;
}
for(int i=id+1;i>=1;i--) cout<<u[a[i]];
cout<<'\n';
}
return 0;
}C-不平衡数组
Solution
01dp
考虑取和不取两种情况。 表示第i位不加1和加1的情况。
- 其他情况
Code
#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
const double eps = 1e-8;
const int NINF = 0xc0c0c0c0;
const int INF = 0x3f3f3f3f;
const ll mod = 1e9 + 7;
const ll N = 1e6 + 5;
ll n,a[N],b[N],f[N][2];
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i]>>b[i];
f[1][0]=0,f[1][1]=b[1];
for(int i=2;i<=n;i++){
if(a[i]==a[i-1]){
f[i][0]=f[i-1][1];
f[i][1]=f[i-1][0]+b[i];
}
else if(a[i]+1==a[i-1]){
f[i][0]=min(f[i-1][0],f[i-1][1]);
f[i][1]=f[i-1][1]+b[i];
}
else if(a[i]==a[i-1]+1){
f[i][0]=f[i-1][0];
f[i][1]=min(f[i-1][1],f[i-1][0])+b[i];
}else{
f[i][0]=min(f[i-1][0],f[i-1][1]);
f[i][1]=min(f[i-1][0],f[i-1][1])+b[i];
}
}
cout<<min(f[n][0],f[n][1])<<'\n';
return 0;
}D-数列统计
Solution
设表示以x结尾,长度为l的数列个数。
数据量较大:预处理组合数前缀积和逆元的前缀积。(这里方法是参考Lskkkno1的
由递推式打表找规律得到答案为。
顺便问下有没有数学方法,就稍微严谨一点的方法可以由递推式推出结论的?
Code
#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
const double eps = 1e-8;
const int NINF = 0xc0c0c0c0;
const int INF = 0x3f3f3f3f;
const ll mod = 911451407;
const ll N = 2e6 + 5;
ll fac[N+5],ifac[N+5];
ll qpow(ll a,ll b){
ll res=1;
while(b>0){
if(b&1) res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
inline ll perm(ll x,ll y){return fac[x]*ifac[x-y]%mod;}
inline ll comb(ll x,ll y){return perm(x,y)*ifac[y]%mod;}
void init(){
fac[0]=1;
for(int i=1;i<=N;i++) fac[i]=1ll*i*fac[i-1]%mod;
ifac[N]=qpow(fac[N],mod-2);
for(int i=N;i;i--) ifac[i-1]=1ll*i*ifac[i]%mod;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
init();
int T;cin>>T;
while(T--){
ll l,x;cin>>l>>x;
cout<<comb(l+x-2,x-1)<<'\n';
}
return 0;
}
京公网安备 11010502036488号