11.03 刷题笔记
11.03 刷题总结
最近效率越来越低
不对,是做题的数量变少了,但是质量还是挺高的
这两天一直在做数学题和容斥题
今天只有四+1道题,但是每一道都是经典,但是不是特别套路
但是今天特别窝囊,因为看到好几道特别难的概率就跑了......
Luogu P7485 「Stoi2031」枫
我有题解了:链接
Luogu P3791 普通数学题
这个其实挺难的,但是在\(jbb\)的指导下,变得异常简单,感谢!!!
所以这个其实是用了数位\(DP\)的思想,使前几位紧贴上界,这样后面的就随机了
最后乘上一个方案数就好了
code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fxt(i,x,y) for(int i=(x);i<=(y);i++)
#define pyt(i,x,y) for(int i=(x);i>=(y);i--)
const int mod=998244353;
int n,m,x,a,b,ans;
map<int,int> mp;
int d(int x){
//cout<<x<<endl;
if(x<0)return 0;
if(mp.find(x)!=mp.end())return mp[x];
int ret=0,l=1,r;
for(;l<=x;l=r+1){
r=x/(x/l);
ret=(ret+(r-l+1)*(x/l)%mod)%mod;
}
return mp[x]=ret;
}
int bas[55];
signed main(){
scanf("%lld%lld%lld",&n,&m,&x);n++;m++;
pyt(i,51,0)bas[i]=bas[i+1]|(1ll<<i);
fxt(i,0,50){
if(!((n>>i)&1))continue;
fxt(j,0,50){
if(!((m>>j)&1))continue;
int mx=max(i,j),mn=min(i,j);
//cout<<i<<" "<<j<<" "<<mx<<endl;
ans=(ans+(1ll<<mn)%mod*(d(((n^(1ll<<i)^m^(1ll<<j)^x)&bas[mx])+(1ll<<mx)-1)-d(((n^(1ll<<i)^m^(1ll<<j)^x)&bas[mx])-1)+mod)%mod)%mod;
}
//cout<<ans<<endl;
}
printf("%lld",ans);
}
Luogu P4640 [ BJWC2008 ] 王之财宝
所以这个容斥被我半个小时就切了,不对忘记多长时间了??..
直接插板法,最后组合数要加起来,就是杨辉三角一列相加可以直接算
加加减减就好了
code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fxt(i,x,y) for(int i=(x);i<=(y);i++)
#define pyt(i,x,y) for(int i=(x);i>=(y);i--)
const int N=1e5+4;
int n,t,m,mod,ans;
int ksm(int x,int y){
int ret=1;
while(y){
if(y&1)ret=ret*x%mod;
x=x*x%mod;y>>=1;
}return ret;
}
int b[20];
int jc[N],inv[N];
int w(int x,int y){
if(x<y)return 0;
return jc[x]*inv[y]%mod*inv[x-y]%mod;
}
int C(int x,int y){
if(y==0)return 1;
return C(x/mod,y/mod)*w(x%mod,y%mod)%mod;
}
int sum[1<<15],num[1<<15],who[1<<15];
signed main(){
scanf("%lld%lld%lld%lld",&n,&t,&m,&mod);
jc[0]=1;fxt(i,1,mod-1)jc[i]=jc[i-1]*i%mod;
inv[0]=1;inv[mod-1]=ksm(jc[mod-1],mod-2);
pyt(i,mod-2,1)inv[i]=inv[i+1]*(i+1)%mod;
ans=C(m+n,n);
fxt(i,1,t)scanf("%lld",&b[i]),who[1<<i-1]=b[i]+1;
int U=(1<<t)-1;
fxt(s,1,U){
num[s]=num[s-(s&-s)]+1;
sum[s]=sum[s-(s&-s)]+who[s&-s];
if(sum[s]>=m)continue;
if(num[s]&1)ans=(ans-C(m-sum[s]+n,n)+mod)%mod;
else ans=(ans+C(m-sum[s]+n,n))%mod;
}
printf("%lld",ans);
}
CF1271D Portals
傻逼\(DP\),直接转移就完事了
越靠后出兵越好,复杂度直接\(\mathcal{O(n^2)}\)
code
#include<bits/stdc++.h>
using namespace std;
#define fxt(i,x,y) for(int i=(x);i<=(y);i++)
#define pyt(i,x,y) for(int i=(x);i>=(y);i--)
const int N=5005;
int n,m,k;
int a[N],b[N],c[N],bl[N];
vector<int> e[N];
int f[N][N],ans=-1;
bool com(int x,int y){return c[x]>c[y];}
signed main(){
scanf("%d%d%d",&n,&m,&k);
fxt(i,1,n)scanf("%d%d%d",&a[i],&b[i],&c[i]),bl[i]=i;
fxt(i,1,m){
int x,y;
scanf("%d%d",&x,&y);
if(x>bl[y])bl[y]=x;
}
fxt(i,1,n)e[bl[i]].push_back(i);
fxt(i,1,n)sort(e[i].begin(),e[i].end(),com);
memset(f,0x8f,sizeof(f));f[0][k]=0;
int now=k;
fxt(i,1,n){
int sum=0,cnt=0;now+=b[i];
fxt(j,a[i],now-b[i])f[i][j+b[i]]=max(f[i][j+b[i]],f[i-1][j]);
for(int x:e[i]){
sum+=c[x];cnt++;
fxt(j,max(cnt-b[i],a[i]),now-b[i]){
f[i][j+b[i]-cnt]=max(f[i][j+b[i]-cnt],f[i-1][j]+sum);
}
}
}
fxt(i,0,5000)ans=max(f[n][i],ans);
printf("%d",ans);
}
CF980D Perfect Groups
说实话这个题是真的水,只是我对负数开根竟然不给我报错!!!
去除一个数中的所有平方因子,这样只有两个数相同的时候才可以放到一组
当然还有\(0\)的情况,\(0\)可以任意放到一组中
直接用\(DP\)维护当前的数值个数就好了
对于每一个数记录他上一次出现的位置
code
#include<bits/stdc++.h>
using namespace std;
#define fxt(i,x,y) for(int i=(x);i<=(y);i++)
#define pyt(i,x,y) for(int i=(x);i>=(y);i--)
const int N=5005;
int n,a[N],ans[N];
int las[N],w;
map<int,int> pos;
int f[N];
signed main(){
scanf("%d",&n);
fxt(i,1,n){
scanf("%d",&a[i]);
if(a[i])fxt(j,2,sqrt(abs(a[i])))
while(abs(a[i])%(j*j)==0)
a[i]/=(j*j);
las[i]=pos[a[i]];
pos[a[i]]=i;
}
fxt(i,1,n){
if(!a[i])w=i;
fxt(j,1,i){
if(las[i]<j)f[j]++;
if(j<=w&&f[j]>1)ans[f[j]-1]++;
else ans[f[j]]++;
}
}
fxt(i,1,n)printf("%d ",ans[i]);
}
QQ:2953174821

浙公网安备 33010602011771号