C
题意: 给定长度为n的数组a,在其中选择若干个数组成数组b,对于1-m这些数,在b中至少存在一个数是他的倍数。如果不能找到,输出-1;如果能找到,输出数组b的最大值减最小值最小的值.
思路: 感觉很综合,没想到捏。双指针,没想到,寄。对于选定的数组成的数组,我们如何检查是否满足条件呢。因为值域只有1e5,我们可以提前预处理出每个数的因子。通过计数来判断1-m的是否每个数都作为因子出现过。
那么怎么找到最大值减最小值最小呢?双指针,因为我们不care数组的具体样子。把数组a排序,双指针可以求出以每个数为起点的满足条件的最短区间,记录下最小值。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
const int mod = 1e9+7;
int n,m,k,T;
vector<int> va[N]; //����
int cnt[N];
int fun(int x)
{
for(int i=1;i*i<=x;++i)
{
if(x%i==0)
{
va[x].push_back(i);
if(i!=x/i) va[x].push_back(x/i);
}
}
}
void solve()
{
cin>>n>>m;
vector<int> a(n);
for(int i=0;i<n;++i) cin>>a[i];
sort(a.begin(),a.end());
int tot = 0;
int ans = 1e9;
for(int l=0,r=0;l<n;++l)
{
while(r<n&&tot<m)
{
for(int &j:va[a[r]])
{
if(j<=m&&++cnt[j]==1) tot++;
}
r++;
}
if(tot==m) ans = min(ans,a[r-1]-a[l]);
for(int &j:va[a[l]])
{
if(j<=m&&--cnt[j]==0) tot--;
}
}
if(ans==1e9) ans = -1;
cout<<ans<<"\n";
}
signed main(void)
{
int tot = 0;
for(int i=1;i<=1e5;++i) fun(i),tot+=va[i].size();
// cout<<tot<<"?\n";
// for(int i=1000;i<=1000+100;++i) cout<<va[i].size()<<"\n";
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
cin>>T;
while(T--) solve();
return 0;
}
D
题意: 给定一颗有根树,树上每个点的权值为1或者0.每个时刻,树上所有节点的权值变为子节点权值的异或和。对于所有初始情况,从全0到全1,所有时刻树中节点的权值和的和。
思路: 观察发现所有节点每个时刻贡献都是2^n-1,一半的情况是1,一半的情况是0.对于叶子显然是如此。对于非叶节点,也是如此。t=0时,一半是1;t=1,根据其子节点的异或和得到其权值,子节点对应的所有情况是全0到全1的,异或和结果是1的全部情况也就是有Cn1 + Cn3 + …,只选出奇数个1的情况,所以一半的情况是1,贡献为2n-1。每个时刻都是如此,因为子节点总是能囊括全部的情况,直到这个节点的所有子节点权值都变成0,以后结果一直是0了。对于叶子,只产生一个时刻的贡献;对于比叶子高一层的节点,产生两个时刻的贡献。以此类推,每个点的贡献是高度乘以2n-1.
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5+10;
const int mod = 1e9+7;
int n,m,k,T;
int d[N];
vector<int> va[N];
void dfs(int cur,int fa)
{
for(int &j:va[cur])
{
if(j==fa) continue;
dfs(j,cur);
d[cur] = max(d[cur],d[j]+1);
}
d[cur] = max(d[cur],1);
}
ll qpow(ll a,int k)
{
ll res = 1;
while(k)
{
if(k&1) res = res * a % mod;
k >>= 1;
a = a * a % mod;
}
return res;
}
void solve()
{
cin>>n;
for(int i=1;i<=n;++i) va[i].clear(),d[i] = 0;
for(int i=0;i<n-1;++i)
{
int x,y; cin>>x>>y;
va[x].push_back(y),va[y].push_back(x);
}
dfs(1,0);
ll t = qpow(2,n-1);
ll ans = 0;
for(int i=1;i<=n;++i)
{
ans = (ans + t*d[i]%mod)%mod;
}
cout<<ans<<"\n";
}
signed main(void)
{
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
cin>>T;
while(T--) solve();
return 0;
}