D
数组长度为2*1e5 ,我们知道如果超过30个非(-1,1)的数字相乘一定是大于查询的值域的
所以如果超过60(30*2)个数字,那么一定不能构成查询的数,而如果小于60个则可以暴力预处理一下,求出并记录,每个值变化时数组的乘积,在查询中直接查询
需要注意的是0是一定可以达到的,只需把一个数变成0,那么数组的乘积都是0
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
#include<set>
#include<map>
using namespace std;
typedef long long LL;
#define int long long
typedef pair<int,int> PII;
const int N=1000010;
int a[N];int n,q;
map<int,int>mp;
void solve(){
cin>>n>>q;
set<int>s;
for(int i=1;i<=n;i++){
cin>>a[i];
s.insert(a[i]);
}
int t=sqrt(1e9)+1;
if(s.size()<=60){
for(auto c:s){
for(int j=c-t;j<=c+t;j++){
int res=1;
for(int i=1;i<=n;i++){
res=res*(a[i]-j);
if(abs(res)>1e9) break;
}
if(abs(res)<=1e9)mp[res]=1;
}
}
}
mp[0]=1;
int m;
while(q--){
cin>>m;
if(mp.count(m)) cout<<"Yes\n";
else cout<<"No\n";
}
}
signed main(){
int t=1;
//cin>>t;
while(t--){
solve();
}
}
F
第二类斯特林数模板
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
#include<set>
#include<map>
using namespace std;
typedef long long LL;
#define int long long
typedef pair<int,int> PII;
const int N=1000010,mod=1e9+7;
int a[N],v[N],w[N],ans[N];
int in[N],inv[N];
int n,m;
int qmi(int a,int b){
int res=1;
while(b){
if(b&1) res=(res*a)%mod;
a=(a*a)%mod;
b>>=1;
}
return res;
}
void inti(){
int res=1;
in[0]=1;
for(int i=1;i<=N;i++){
in[i]=(in[i-1]*i)%mod;
}
}
void solve(){
cin>>n>>m;
inti();
int ans=0;
for(int i=0;i<=m;i++){
ans=(ans+(qmi(-1,m-i)*qmi(i,n))%mod*qmi(in[i]*in[m-i]%mod,mod-2))%mod;
}
cout<<ans<<endl;
}
signed main(){
int t=1;
while(t--){
solve();
}
}
H
让我们看这样一个二进制数
我们可以O(n)求出它对应的数组的和
如何考虑更优解
我们注意到如果把最高位的1改成0,我们就可以把更低的位全部变成1
这么做的贡献为所有
减去所有\sum a[i] &10000000=10000000
这样我们可以尝试去掉每一位1,然后O(n)求一下和,取最大值即是答案
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
#include<set>
#include<map>
using namespace std;
typedef long long LL;
#define int long long
typedef pair<int,int> PII;
const int N=1000010;
int a[N],v[N],w[N],ans[N];int n,m;
int get(int x){
int res=0;
for(int i=1;i<=n;i++){
if((w[i]&x)==w[i]) res+=v[i];
}
return res;
}
void solve(){
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>v[i]>>w[i];
}
int ans=get(m);
for(int i=m;i;i-=(i&(-i))){
ans=max(ans,get(i-1));
}
cout<<ans<<endl;
}
signed main(){
int t=1;
cin>>t;
while(t--){
solve();
}
}
J
奇妙的二分
枚举最大距离
二分的过程中尝试
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
#include<set>
#include<map>
using namespace std;
typedef long long LL;
#define int long long
typedef pair<int,int> PII;
const int N=1000010;
int a[N];
void solve(){
int x,y,w;
int n;
cin>>n>>x>>y;
for(int i=1;i<=n;i++){
cin>>a[i];
}
auto check=[&](int d){
int last=y;
set<int>s;
if(abs(x-y)<=d) s.insert(x);
for(int i=1;i<=n;i++){
if(s.size() && abs(a[i]-last)<=d) s.insert(last);
while(s.size() && *s.begin()<a[i]-d) s.erase(s.begin());
while(s.size() && *s.rbegin()>a[i]+d) s.erase(*s.rbegin());
last=a[i];
}
return s.size();
};
int l=0,r=1e9+1;
while(l<r){
int mid=l+r>>1;
if(!check(mid)){
l=mid+1;
}else{
r=mid;
}
}
cout<<l<<endl;
}
signed main(){
int t=1;
while(t--){
solve();
}
}
K
模拟一下可知
部分题目连接在一起可以形成一个环(加上其他连向环的边形成基环树,这里如果环内确定下来,那么环外的选择就已经确定了,可以反推,所有只需要考虑环内的数量即可),如果环头和环尾不一致则不成一个方案。
我们直接从环上的点开始模拟,依次求出每个选择是否可行(根据上文的方法)
求出所有环的方案数相乘即是答案
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
#include<set>
#include<map>
using namespace std;
typedef long long LL;
#define int long long
typedef pair<int,int> PII;
const int N=1000010,mod=998244353;
int a[N],d[N];
bool st[N];
string str[N];
void solve(){
int n;
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i]>>str[i];
d[a[i]]++;
}
queue<int>q;
for(int i=1;i<=n;i++){
if(!d[i]) q.push(i);
}
while(q.size()){
int t=q.front();
q.pop();
st[t]=1;
if(--d[a[t]]==0){
q.push(a[t]);
}
}
int ans=1;
for(int i=1;i<=n;i++){
if(st[i]) continue;
//cout<<i<<endl;
int res=0;
for(int j=0;j<5;j++){
int now=i;
st[now]=1;
int nowop=j;
while(1){
nowop=str[now][nowop]-'A';
now=a[now];
st[now]=1;
if(now==i)break;
}
if(nowop==j)res++;
}
ans=(ans*res)%mod;
}
cout<<ans<<endl;
}
signed main(){
int t=1;
//cin>>t;
while(t--){
solve();
}
}