A
using namespace std;
#include <bits/stdc++.h>
#define int long long
void solve()
{
int n,m;
cin>>n>>m;
int sum=0;
for(int i=1;i<=n;i++)
{
int xx;
cin>>xx;
sum+=xx;
}
if(sum==m)
cout<<"YES"<<"\n";
else
cout<<"NO"<<"\n";
}
signed main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int _ = 1;
cin >> _;
while (_--)
solve();
return 0;
}
B
using namespace std;
#include <bits/stdc++.h>
#define int long long
const int N=1e5+5;
int flag[N],prime[N],pnum;
void CreatePrime()
{
pnum=0;
for(int i=0;i<N;i++)
{
flag[i]=1;
}
for(int i=2;i<=N;i++)
{
if(flag[i]==1)
prime[pnum++]=i;
for(int j=0;j<pnum&&prime[j]*i<=N;j++)
{
flag[prime[j]*i]=0;
if(i%prime[j]==0)
break;
}
}
}
void solve()
{
int n;
cin>>n;
int xx=(n-1)*4;
int yy=0;
while(flag[xx]==0||flag[yy])
{
xx++;
yy++;
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(i==j)
cout<<yy<<" ";
else
cout<<4<<" ";
}
cout<<endl;
}
}
signed main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
CreatePrime();
int _ = 1;
cin >> _;
while (_--)
solve();
return 0;
}
C
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int mod=1e9+7;
vector<int>uu,vv;
const int kk=1e3+5;
int inv[kk];
void getInv()
{
inv[1]=1;
for(int i=2;i<kk;i++)
inv[i]=(mod-mod/i)*inv[mod%i]%mod;
}
int fact[kk];
int invfact[kk];
void init()
{
fact[0]=1;
invfact[0]=1;
for(int i=1;i<kk;i++)
{
fact[i]=fact[i-1]*i%mod;
invfact[i]=invfact[i-1]*inv[i]%mod;
}
}
int getC(int m,int n)
{
if(m<0||m>n)
return 0;
return fact[n]*invfact[m]%mod*invfact[n-m]%mod;
}
void solve()
{
uu.clear();
vv.clear();
int n,x,pos;
cin>>n>>x>>pos;
int l=0,r=n;
while(l<r)
{
int mid=(l+r)/2;
if(mid<=pos)
{
l=mid+1;
if(mid!=pos)
uu.push_back(mid);
}
else
{
r=mid;
vv.push_back(mid);
}
}
int a=uu.size();
int b=vv.size();
int res=getC(a,x-1)*getC(b,n-x)%mod;
int ans=fact[a]*fact[b]%mod*fact[n-a-b-1]%mod;
res=res*ans%mod;
cout<<res;
}
signed main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
getInv();
init();
int _ = 1;
//cin >> _;
while (_--)
solve();
return 0;
}
D
题意: 有一颗有根树,根为1,每个节点上面都有一个权值,这些权值都会不断向下面的分支移动,问使得每个叶节点上权值最大的值最小是多少。
题解: 可以统计每个子树的权值和是多少,那么每个叶节点最后的权值就是总的权值和/叶节点数目。这个结论一开始就是这么猜的,然后一直觉得证明不了,感觉无法让左边分支的节点走到右边分支,但是当这种情况出现时,答案会在下面的子树取得。证明不了,就口胡数学归纳法过了吧。
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=2e5+5;
struct node
{
int v,next;
};
node no[maxn*10];
int head[maxn];
int cnt=1;
int a[maxn];
int b[maxn];
void init()
{
memset(head,0,sizeof(head));
}
void add(int x,int y)
{
no[cnt].v=y;
no[cnt].next=head[x];
head[x]=cnt;
cnt++;
}
int ans=0;
void dfs(int u)
{
if(head[u]==0)
b[u]=1;
else
b[u]=0;
for(int i=head[u];i;i=no[i].next)
{
int v=no[i].v;
dfs(v);
b[u]+=b[v];
a[u]+=a[v];
}
ans=max(ans,(a[u]+b[u]-1)/b[u]);
}
void solve()
{
int n;
cin>>n;
for(int i=2;i<=n;i++)
{
int x;
cin>>x;
add(x,i);
}
for(int i=1;i<=n;i++)
cin>>a[i];
dfs(1);
cout<<ans;
}
signed main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int _ = 1;
//cin >> _;
while (_--)
solve();
return 0;
}
E
题意:给你一个数组,求子数组mex 的集合S ,求mex(S);
思路:求子数组会不会出现 mex=x的情况 ,有的话肯定在相邻的两个x之间及现在和last 之间,并且1-x-1的出现的last最小值肯定比last[x]大,才是,然后直接维护更新last, 维护last 的时候记得最后一段。
很显然找一段的最小值线段树维护,单点更新。
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int inf=1e9+5;
const int maxn=1e5+5;
int a[maxn];
int last[maxn];
set<int>se;
int tree[maxn*4];
void build(int l,int r,int t)
{
if(l==r)
tree[t]=last[l];
else
{
int mid=(l+r)>>1;
build(l,mid,t<<1);
build(mid+1,r,t<<1|1);
tree[t]=min(tree[t<<1],tree[t<<1|1]);
}
}
void update(int l,int r,int t,int x,int y)
{
if(l==r)
{
tree[t]=y;
return;
}
int mid=(l+r)>>1;
if(x<=mid)
update(l,mid,t<<1,x,y);
else
update(mid+1,r,t<<1|1,x,y);
tree[t]=min(tree[t<<1],tree[t<<1|1]);
}
int query(int l,int r,int t,int L,int R)
{
if(l>=L&&r<=R)
return tree[t];
if(l>R||r<L)
return inf;
int mid=(l+r)>>1;
int ans=inf;
if(mid>=L)
ans=min(ans,query(l,mid,t<<1,L,R));
if(mid<R)
ans=min(ans,query(mid+1,r,t<<1|1,L,R));
return ans;
}
void solve()
{
se.clear();
memset(last,0,sizeof(last));
int n;
cin>>n;
build(1,n,1);
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
for(int i=1;i<=n;i++)
{
int xx=a[i];
if(xx==1)
se.insert(2);
else
{
se.insert(1);
if(query(1,n,1,1,xx-1)>last[xx])
se.insert(xx);
}
last[xx]=i;
update(1,n,1,xx,i);
}
for(int i=2;i<=n+1;i++)
{
if(query(1,n,1,1,i-1)>last[i])
se.insert(i);
}
int now=1;
for(auto s:se)
{
if(s!=now)
{
cout<<now;
return;
}
now++;
}
cout<<now;
}
signed main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int _ = 1;
//cin >> _;
while (_--)
solve();
return 0;
}
F
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=1e5+5;
const int mod=998244353;
int num[maxn];
int dp[maxn];
int fastpow(int a,int n)
{
if(n<0)
return 0;
int res=1;
int temp=a;
while(n)
{
if(n&1)
res=res*temp%mod;
temp=temp*temp%mod;
n>>=1;
}
return res%mod;
}
void solve()
{
int N=1e5;
memset(dp,0,sizeof(dp));
memset(num,0,sizeof(num));
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
int x,y;
cin>>x>>y;
num[x]+=y;
}
int c,sm,sm2,w;
for(int i=N;i;i--)
{
c=sm=sm2=w=0;
for(int j=i;j<=N;j+=i)
{
c=c+num[j];
sm=(sm+j*j%mod*num[j]%mod)%mod;
sm2=(sm2+w*2%mod*j%mod*num[j]%mod+j*j%mod*num[j]%mod*(num[j]-1)%mod)%mod;
w=(w+num[j]*j%mod)%mod;
dp[i]=(dp[i]-dp[j]+mod)%mod;
}
dp[i]=(dp[i]+(c-1)%mod*sm%mod*fastpow(2,c-2)%mod+sm2*((c-2)%mod*fastpow(2,c-3)%mod+fastpow(2,c-2))%mod)%mod;
}
cout<<dp[1];
}
signed main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int _ = 1;
//cin >> _;
while (_--)
solve();
return 0;
}
反演
一个函数 f(n)=g(i)的和 i是n的因子或者倍数,g[n]=f[i]*mu[n/i 或者 i/n]的和叫莫比乌斯反演
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=1e5+5;
const int mod=998244353;
int num[maxn];
int dp[maxn];
int mu[maxn];
bool isnp[maxn];
vector<int>primes;
void init(int n)
{
memset(isnp,false,sizeof(isnp));
primes.clear();
mu[1]=1;
for(int i=2;i<=n;i++)
{
if(!isnp[i])
primes.push_back(i),mu[i]=-1;
for(int p:primes)
{
if(p*i>n)
break;
isnp[p*i]=i;
if(i%p==0)
{
mu[p*i]=0;
break;
}
else
mu[p*i]=mu[p]*mu[i];
}
}
}
int fastpow(int a,int n)
{
if(n<0)
return 0;
int res=1;
int temp=a;
while(n)
{
if(n&1)
res=res*temp%mod;
temp=temp*temp%mod;
n>>=1;
}
return res%mod;
}
void solve()
{
int N=1e5;
memset(dp,0,sizeof(dp));
memset(num,0,sizeof(num));
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
int x,y;
cin>>x>>y;
num[x]+=y;
}
int c,sm,sm2,w;
for(int i=N;i;i--)
{
c=sm=sm2=w=0;
for(int j=i;j<=N;j+=i)
{
c=c+num[j];
sm=(sm+j*j%mod*num[j]%mod)%mod;
sm2=(sm2+w*2%mod*j%mod*num[j]%mod+j*j%mod*num[j]%mod*(num[j]-1)%mod)%mod;
w=(w+num[j]*j%mod)%mod;
}
dp[i]=(dp[i]+(c-1)%mod*sm%mod*fastpow(2,c-2)%mod+sm2%mod*((c-2)%mod*fastpow(2,c-3)%mod+fastpow(2,c-2))%mod)%mod;
}
int ans=0;
for(int i=1;i<=N;i++)
{
if(dp[i]==0)
continue;
ans=(ans+mod+mu[i]*dp[i])%mod;
}
cout<<ans;
}
signed main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int _ = 1;
int n=1e5;
init(n);
//cin >> _;
while (_--)
solve();
return 0;
}