小结+组合数学+模拟+思维
Posted 钟钟终
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了小结+组合数学+模拟+思维相关的知识,希望对你有一定的参考价值。
最近有点松懈了,我的问题,总会莫名感觉压力很大。其实哪有什么压力,认真把每件事做好。
认真学好专业课,上课认真听讲,及时完成作业就好。
算法学习是最近两个月绝对的核心,是提高自己的关键一环。
对于保研考研,不要过多担心了,做好自己能做的最大限度,剩下的你把控不了。
日常搭配:思维+省选+区域赛题
静下心来,加油啊
P4562 [JXOI2018]游戏
题意:对于一个区间l~r,长度为r-l+1,每次可以记录一个数以及它的向上整数倍的区间内的数;问不同次数的各种方案将所有数字覆盖的累加和。
思路:
1.数据范围可达1e7,因此是一个数学题或者O(n)方法做出。
2.采用素数筛的思想求出覆盖l~r最少需要多少次。
3.组合数学思考公式。考虑消去区间需要的次数i在sum~n之间。第i次正好可将区间覆盖(乘上sum),因此前(i-1)个数可随意放置,对于后半段数字的选取为C(n-sum,n-i)
公式:C(n-sum,n-i)*(i-1)!*sum*(n-i)!
,可进行化简。
最后,需要对逆元提前预处理,O(n)过题
fac[0]=fac[1]=1;
for(int i=1;i<=r;i++) fac[i]=fac[i-1]*i%mod;
inv[r]=qpow(fac[r],mod-2);
#include <bits/stdc++.h>
#define int long long
#define endl '\\n'
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
using namespace std;
const int inf=1e18;
const int N=1e7+5;
const int mod=1e9+7;
int n,fac[N],inv[N];
int l,r;
bool vis[N];
int qpow(int x,int y)
int res=1;
while(y)
if(y&1) res=res*x%mod;
x=x*x%mod;y>>=1;
return res;
int getinv(int x) return qpow(x,mod-2);
int C(int n,int m)
return (fac[n]*inv[fac[m]]%mod)*inv[fac[n-m]]%mod;
void solve()
cin>>l>>r;
n=r-l+1;
fac[0]=fac[1]=1;
for(int i=1;i<=r;i++) fac[i]=fac[i-1]*i%mod;
inv[r]=qpow(fac[r],mod-2);
for(int i=r;i;i--) inv[i-1]=i*inv[i]%mod;
int sum=0;
for(int i=l;i<=r;i++)
if(!vis[i])
sum++;
for(int j=i<<1;j<=r;j+=i)
vis[j]=1;
int ans=0;
for(int i=sum;i<=n;i++)
ans=(ans+sum*fac[n-sum]%mod*inv[i-sum]%mod*fac[i]%mod)%mod;
cout<<ans<<endl;
//cout<<sum<<endl;
signed main()
//ios;
//int T;cin>>T;
//while(T--)
solve();
return 0;
题全补完了。但这场牛客打得很烂,被B题自己写的自定义排序弄得心态崩了,编译器上能运行,牛客编译器总是报错,以后还是不要尝试这种写法,老实写map不好嘛。还不情愿换个方法,总觉得自己没错……
D .数学考试
这个dp要我想估计要想好久,代码理解的队友的,感觉很常规的状态设计。
对于每道题i,从各个k开始能获得的最大分数,都是取最大值,考虑全就好,没有技巧性的初始化。
四种状态分析:
1.直接对于该k值,继承上一题此时的k值,压力值不变的情况。
2.若此时j<=b[i]
,则经验值直接累加f[t][j]=max(f[t][j],f[!t][j]+j*a[i]);
3.因为做出一题后,可选择增加q[i],若上一次做完j-q[i]<=b[i],
则方程为f[t][j]=max(f[t][j],f[!t][j-q[i]]+(j-q[i])*a[i]);
,否则可继承f[t][j-q[i]]
4.与情况三类似,保证不超过k值即可。
但是需要用滚动数组,和之前做的01背包变型以前,只涉及到前一个状态。
#include <bits/stdc++.h>
#define int long long
#define endl '\\n'
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
using namespace std;
const int inf=1e18;
const int N=1e4+5;
const int mod=1e9+7;
int n,k,a[N],b[N],q[N],w[N],f[2][5005];
void solve()
cin>>n>>k;
for(int i=1;i<=n;i++) cin>>a[i]>>b[i]>>q[i]>>w[i];
int t=0;
for(int i=1;i<=n;i++)
t=!t;
for(int j=0;j<=k;j++)
f[t][j]=max(f[t][j],f[!t][j]);
if(j<=b[i])
f[t][j]=max(f[t][j],f[!t][j]+j*a[i]);
if(j+w[i]<=k)
if(j+w[i]<=b[i])
f[t][j]=max(f[t][j],f[!t][j+w[i]]+(j+w[i])*a[i]);
else
f[t][j]=max(f[t][j],f[!t][j+w[i]]);
if(j-q[i]>=0)
if(j-q[i]<=b[i])
f[t][j]=max(f[t][j],f[!t][j-q[i]]+(j-q[i])*a[i]);
else
f[t][j]=max(f[t][j],f[!t][j-q[i]]);
int ans=0;
for(int i=0;i<=k;i++) ans=max(ans,f[t][i]);
cout<<ans<<endl;
signed main()
//ios;
//int T;cin>>T;
//while(T--)
solve();
return 0;
草方块与牛排
对于此类的题,我总是把握不好,虽然说这题我还是20分钟内ac了,依旧是短板,从上海站的B题就看出来了,全队只有我去想每个点和地雷的影响范围了。
思路:
必须要对满足(n-2)%8==0才可以。剩下就是组合成2*3的小方格铺满。
#include <bits/stdc++.h>
#define int long long
#define endl '\\n'
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
using namespace std;
const int inf=1e18;
const int N=1e4+5;
const int mod=1e9+7;
int n;
void solve()
cin>>n;
int num=n*n;
if((num-4)%8)
cout<<-1<<endl;return;
cout<<(num-4)/8*2<<endl;
if((n-2)%4==0)
int g=(n-2)/4;
int k=3;
for(int i=1;i<=g;i++)
cout<<k<<" "<<k+1<<" "<<k+2<<" "<<k+n<<endl;
cout<<k+3<<" "<<k+3+n<<" "<<k+3+n-1<<" "<<k+3+n-2<<endl;
k+=4;
k+=n;
for(int s=1;s<=n/2;s++)
int kk=k;
for(int i=1;i<=n/4;i++)
cout<<kk<<" "<<kk+1<<" "<<kk+n<<" "<<kk+2*n<<endl;
cout<<kk+3*n<<" "<<kk+3*n+1<<" "<<kk+2*n+1<<" "<<kk+n+1<<endl;
kk+=4*n;
k+=2;
/*
else if((num-2)%4==2)
int g=(n-2)/4;
int k=3;
for(int i=1;i<=g;i++)
cout<<k<<" "<<k+1<<" "<<k+2<<" "<<k-2+n<<endl;
cout<<k+3<<" "<<k+3+n<<" "<<k+3+n-1<<" "<<k+3+n-2<<endl;
k+=4;
for(int i=1;i<=n/4;i++)
cout<<k<<" "<<k+1<<" "<<k+n<<" "<<k+2*n<<endl;
cout<<k+3*n<<" "<<k+3*n+1<<" "<<k+2*n+1<<" "<<k+n+1<<endl;
*/
signed main()
//ios;
//int T;cin>>T;
//while(T--)
solve();
return 0;
B. Mine Sweeper II
应该从nm/2这个角度思考。若是不相同的点小于等于nm/2,则直接输出A;若是大于,需要输出反图。我真的想错了当时。。。。
#include <bits/stdc++.h>
#define int long long
#define endl '\\n'
#define ios (ios::sync_with_stdio(false),cin.tie(0),cout.tie(0))
using namespace std;
const int inf=1e18;
const int N=7e6+5;
const int mod=1e9+7;
bool cmp(int a,int b)return a>b;
int n,m;
char a[1005][1005],b[1005][1005];
void solve()
cin>>n>>m;
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) cin>>a[i][j];
int ans=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cin>>b[i][j];
if(a[i][j]!=b[i][j])
ans++;
if(ans<=(m*n/2))
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cout<<a[i][j];
cout<<endl;
else
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(a[i][j]=='.') cout<<"X";
else cout<<".";
cout<<endl;
signed main()
//ios;
//int T;cin>>T;
//while(T--)
solve();
return 0;
D题的二分自己写了一个,写了很久但还没调出来,先欠一下
以上是关于小结+组合数学+模拟+思维的主要内容,如果未能解决你的问题,请参考以下文章