模拟赛改题记录
12-15模拟赛
其实很简单,其实真的很烂到家了:(
T1 坦克
考虑一次性快进到减少或者减少的时间,需要的回合数,然后算出回合之后的状态 。
重复这个过程,直到某一方的坦克被打完,时间复杂度
很简单的一道小模拟,记录每回合的损失情况,处理好盈余攻击力即可
代码如下(有些丑)
#include<bits/stdc++.h>
using namespace std;
int T;
int n,m,a,b,vm,vn,jx,jy,bn,bm;
int main(){
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin>>T;
for(int i=1;i<=T;i++){
cin>>n>>m>>a>>b;
vm=a,vn=b;//盈余攻击力
while(n&&m){
jx=jy=0;//每回合双方会被消灭的坦克数
int xn=n,xm=m;//双方攻击力
if(xn>=vm){
xn-=vm,jy++;
if(xn>=a){
bm=xn/a;
jy+=bm;
if(xn%a) vm=a-(xn%a);
else vm=a;
}
else vm=a-xn;
}
else vm-=xn;
if(xm>=vn){
xm-=vn,jx++;
if(xm>=b){
bn=xm/b;
jx+=bn;
if(xm%b) vn=b-(xm%b);
else vn=b;
}
else vn=b-xm;
}
else vn-=xm;
n-=jx,m-=jy;
if(n<=0){
cout<<"0"<<"\n";
break;
}
else if(m<=0){
cout<<n<<"\n";
break;
}
}
}
return 0;
}
但是我的赛时代码成功的零分了(大胜利
补充 当然我只记住了y0,y1,yn,警钟撅烂
T2 火柴棍
csp2024-j组T3,只是加了一个取模
代码如下
#include<bits/stdc++.h>
using namespace std;
const long long mod=998244853;
int T,n,num;
long long pw[150000],lz[150000],ans;
int main(){
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
pw[0]=1;
for(int i=1;i<=149999;i++) lz[i]=(lz[i-1]*10+1)%mod,pw[i]=pw[i-1]*10%mod;
cin>>T;
while(T--){
cin>>n;
if(n<7){
if(n==2) cout<<"1\n";
if(n==3) cout<<"7\n";
if(n==4) cout<<"4\n";
if(n==5) cout<<"2\n";
if(n==6) cout<<"0\n";
continue;
}
num=n/7,n=n%7,ans=0;
if(n==1) num--,ans=10;
if(n==2) ans=1;
if(n==3){
if(num>1) num-=2,ans=200;
else num--, ans=22;
}
if(n==4) num--,ans=20;
if(n==5) ans=2;
if(n==6) ans=6;
cout<<(ans*pw[num]%mod+lz[num]%mod*8%mod)%mod<<"\n";
}
return 0;
}
分讨模数,预处理8的字符串即可
以后这种大考结束后,切记把题都看一遍,改一遍,说不定哪天就会考到
T3 子集计数
计数DP是比较容易想到的,暴力做法就是每次枚举从
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int n,a[100005],dp[100005];
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++){
dp[i]=1;
for(int j=1;j<i;j++){
if(a[j]<=a[i]&&(a[j]|a[i])==a[i])dp[i]+=dp[j];
}
cout<<dp[i]<<"\n";
}
return 0;
}
考虑优化:
观察到数据范围
1、从 的子集出发:
设
转移时枚举
转移后
这样的时间复杂度是
2、从包含 的集合出发:
设
转移时
转移后枚举
时间复杂度仍为
然后呢?
我们发现两个转移方法的复杂度瓶颈都在枚举包含或包含于的集合上,这是直接跟
那么对单个
同样的,
形式化的,我们设
转移时枚举
转移后枚举
时间复杂度
代码如下
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mod 998244353
ll n,a[100005],m;
ll f[100005],g[300][300];
int main(){
// freopen("count.in","r",stdin);
// freopen("ans.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
f[i]=1;
}
for(int i=1;i<=n;i++){
int x=a[i]&255;
for(int t=0;t<=x;t++){
if((t|x)==x) f[i]=(f[i]+g[a[i]>>8][t])%mod;
}
for(int s=0;s<=255;s++){
if(((a[i]>>8)|s)==s) g[s][a[i]&255]=(g[s][a[i]&255]+f[i])%mod;
}
cout<<f[i]%mod<<"\n";
}
return 0;
}
DP还是要多练练,千万不能产生畏难心理
T4 排列
一道dp好题
%20
对于
#include<bits/stdc++.h>
using namespace std;
int n;
bool p[15]={0};
int a[15];
int sum=0;
void dfs(int x){
if(x>n){
sum++;
return ;
}
for(int i=1;i<=n;i++){
if(p[i]==0){
if(x!=1){
if(a[x-1]%i>2) continue;
if(x==n&&i%a[1]>2) continue;
}
p[i]=1,a[x]=i;
dfs(x+1);
p[i]=0;
}
}
}
int main(){
cin>>n;
dfs(1);
cout<<sum;
return 0;
}
%60
切入正题:DP
我们通过打表可以发现,若一个序列是好的序列,其必为两个递减的序列拼凑后,从任意地方断开,前后调序重组得到的,像样例里给的4的“好的序列”,可以发现以1开头的4个序列经过如上过程后也可以变成其他序列。
因为对于相邻两数
那么必然递减,到1或2结束
选择的问题可以看作从小到大把每个数依次放入集合,这个过程当然是可以dp的
设
那么就可以得到
#include<bits/stdc++.h>
using namespace std;
const long long mod=1e9+7;
long long ans;
int dp[6005][6005],n;
int main(){
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
dp[2][1]=1;
cin>>n;
for(int i=1;i<n;i++){
for(int j=1;j<i;j++){
if(i!=j) dp[i+1][j]=(dp[i+1][j]+dp[i][j])%mod;
if(!j||(i+1)%j<=2) dp[i+1][i]=(dp[i+1][i]+dp[i][j])%mod;
}
}
for(int i=1;i<=n;i++){
ans=(ans+dp[n][i])%mod;
}
cout<<ans*n%mod;
return 0;
}
%100
考虑滚动掉第一维,第二位的有效状态位很稀疏
第一种转移,一定满足条件,直接继承即可
第二种转移,因为
维护一下转移即可
代码如下
#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
const int N=1e6+50;
#define ll long long
int n,dp[N],ans;
int main(){
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin>>n;
if(n==1){
cout<<"1\n";
return 0;
}
dp[1]=1;
for(int j=1;j<=n-1;j++){
if(j<=3) for(int i=j+1;i<n;i++) dp[i]=(dp[i]+dp[j])%mod;
else
for(int k=-1;k<=1;k++)
for(int i=j+k;i<n;i+=j)
if(j<i) dp[i]=(dp[i]+dp[j])%mod;
}
for(int i=1;i<=n;i++) ans=(ans+dp[i])%mod;
cout<<1ll*ans*n%mod;
return 0;
}
下次可不能再打这么烂了(叹气
本文来自博客园,作者:zhangch_qwq,转载请注明原文链接:https://www.cnblogs.com/zhangchenhua-awa/p/18608773
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步