寒假训练营6

阿宁的倍数

思路

对于这一个数,把他可以在那里提供贡献(也就是他的因子的地方都加上),然后就可以使用二分直接计算贡献。
而不是考虑一个一个的暴力

代码

#include <bits/stdc++.h>
using namespace std;
const int M=2e5+5;
vector<int>v[M];
vector<int>fac[M];
int a[M*2];
void init(int n=2e5) {
for(int i=1;i<=n;i++)
for(int j=i;j<=n;j+=i)
fac[j].push_back(i);//预处理出我的因子
}
void add(int x,int pos) {
a[pos]=x;
for(auto i:fac[x])
v[i].push_back(pos);
}
int main() {
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
init();
int n,q;cin>>n>>q;
for(int i=1;i<=n;i++) {
int x;cin>>x;
add(x,i);
}
for(int i=1;i<=q;i++) {
int op,x;
cin>>op>>x;
if(op==2)cout<<v[a[x]].size()-(lower_bound(v[a[x]].begin(),v[a[x]].end(),x)-v[a[x]].begin()+1)<<'\n';
else add(x,++n);
}
return 0;
}
//只看前面,不看后面,因子数是有限的,所以这样子是完全可以的
//根据某个东西,将他们进行分类,然后实现O1的查找
//也就是直接插入进行查找

阿宁的生成树

思路

首先lcm>=gcd,所以,能用gcd,就不要使用lcm
然后把最初的集合看成只有1这个点,i>k+1的话,就可以都加进来,并且gcd == 1
然后找到一个大的质数p,那么只要小于p-k的数,都是可以直接gcd == 1
对于剩下的这些数据,能找gcd的话,也就是p,n之间了,可以直接暴力枚举,因为质数的分布是比较密集的

代码

#include <bits/stdc++.h>
using namespace std;
using ll=long long;
const int M=2e5+5;
bool st[M];
int n,k;
vector<int>v;
ll ans;
int main() {
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
cin>>n>>k;
bool flag=0;//没有找到这个质数
for(int i=n;i>=k+2;i--) {
ans++;
if(!flag) {//为什么只有这些数才会被加进区间里面呀
bool f=0;
for(int j=2;j*j<=i;j++)
if(i%j==0) {
f=1;
break;
}
if(!f)flag=1;
else v.push_back(i);
}//首先是找到那个大的质数
int u=i-k-1;
if(u>1&&u<=k+1) {
if(flag)ans++;
else {
int mn=1e9;
for(auto x:v)mn=min(mn,__gcd(u,x));
ans+=mn;
}
st[u]=1;
}
}
for(int i=2;i<=min(n,k+1);i++)
if(!st[i])ans+=i;
cout<<ans;
return 0;
}
//暴力的部分只需要考虑那个质数也就可以了,因为剩下的是一定可以做gcd的,也就是权值为1
//质数分布是很密集的,所以暴力的部分是很小的

阿宁睡大觉

思路

因为m比较小,容易想到状压。
总体思路是容斥,但是具体的方案数还是需要进行分析的。
然后用排列组合进行计算就可以了

代码

//利用容斥进行计算就可以了
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int M=2e5+5,mod=1e9+7;
using pii=pair<int,int>;
int kpow(int a,int b) {
int ans=1;
while(b) {
if(b&1)ans=ans*a%mod;
b>>=1;
a=a*a%mod;
}
return ans;
}
int fact[M],infact[M];
void init(int n=2e5+5) {
fact[0]=infact[0]=1;
for(int i=1;i<=n;i++) {
fact[i]=fact[i-1]*i%mod;
infact[i]=kpow(fact[i],mod-2);
}
}
int C(int a,int b) {
return fact[a]*infact[b]%mod*infact[a-b]%mod;
}
pii a[15];
signed main() {
init();
int n,m;
cin>>n>>m;
for(int i=0;i<m;i++)cin>>a[i].first>>a[i].second;
int ans=kpow(2,n-1);
for(int i=1;i<(1<<m);i++) {
int f=1;
vector<pii>v;
v.push_back({1,1});
for(int j=0;j<m;j++)
if(i>>j&1)v.push_back(a[j]),f=-f;//这样子看一下子就可以了
sort(v.begin(),v.end());
int siz=v.size()-1;
//我是最后一个可以去到的位置
int tmp=kpow(2,n+1-(v[siz].first+v[siz].second));
for(int j=1;j<=siz;j++) {
if(v[j].second>=v[j-1].second) {
int x=v[j].first-v[j-1].first;
int y=v[j].second-v[j-1].second;
tmp=tmp*C(x+y,x)%mod;
}
else tmp=0;
}
ans=((ans+tmp*f)%mod+mod)%mod;
}
cout<<ans;
return 0;
}
//也就是容斥进行计算
//每一种情况的话,看这一个与上一个的关系就可以了
//具体情况的话,要把每一种都算出来才是可以的
posted @   basicecho  阅读(18)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示