A - Square Counting
直接能填就填n*n就填,不然全0啥的即可
#include<bits/stdc++.h>
using namespace std;
const int N = 3e5+10,mod=998244353;
#define int long long
typedef long long LL;
typedef pair<int, int> PII;
typedef unsigned long long ULL;const long long inf=1e17;
using node=tuple<int,int,int,int>;
int n,m,k;
int a[N],s[N];
int f[N];
vector<int> g[N];
void solve()
{cin>>n>>m;cout<<m/(n*n)<<"\n";
}signed main()
{cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);int t=1;cin>>t;while(t--) solve();
}
B - Quality vs Quantity
贪心嘛,拿最小的数和最大的数总和比就行,个数只多1即可枚举最大的数拿了几个就好
#include<bits/stdc++.h>
using namespace std;
const int N = 3e5+10,mod=998244353;
#define int long long
typedef long long LL;
typedef pair<int, int> PII;
typedef unsigned long long ULL;const long long inf=1e17;
using node=tuple<int,int,int,int>;
int n,m,k;
int a[N],s[N];
int f[N];
vector<int> g[N];
void solve()
{cin>>n;for(int i=1;i<=n;i++) cin>>a[i];sort(a+1,a+1+n);vector<int> s(n+10);for(int i=1;i<=n;i++) s[i]=s[i-1]+a[i];for(int i=n;i>=1;i--){int r=s[n]-s[i-1];if((n-i+1)+1>=i) break;int l=s[(n-i+1)+1];if(r>l){cout<<"YES\n";return ;}}cout<<"NO\n";
}signed main()
{cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);int t=1;cin>>t;while(t--) solve();
}
C:
就是1e12里面的阶乘就15个,然后二进制枚举选哪些数,然后总和减去
然后就用二进制填就好了(一个数能拆解成不同的二进制数)
#include<bits/stdc++.h>
using namespace std;
const int N = 3e5+10,mod=998244353;
#define int long long
typedef long long LL;
typedef pair<int, int> PII;
typedef unsigned long long ULL;const long long inf=1e17;
using node=tuple<int,int,int,int>;
int n,m,k;
vector<int> fact;
void init()
{int res=1;for(int i=1;i<N;i++){res*=i;fact.push_back(res);if(res>=1e12) break;}// res=1;// for(int i=1;i<N;i++){// res=res*2;// a.push_back(res);// if(res>=1e12) break;// }// sort(a.begin(),a.end());// a.erase(unique(a.begin(),a.end()),a.end());
}
void solve()
{cin>>n;auto get=[&](int x,int v){int cnt=0;for(int i=0;i<=50;i++){if(x>>i&1){cnt++;if((1ll<<i)==v) return 100000ll;}}return cnt;};int res=get(n,0);int m=fact.size();for(int i=0;i<1<<m;i++){int s=0,c=0;for(int j=0;j<m;j++){if(i>>j&1){c++;s+=fact[j];}}if(s<=n){res=min(res,c+get(n-s,0));}}cout<<res<<"\n";
}signed main()
{cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);int t=1;init();// cout<<fact.size()<<"\n";cin>>t;while(t--) solve();
}
D:
比较裸的树形dp吧
有个结论是如果当前点选了,相邻的点不能选,不然 w[u]=w[x],但是又由于这是一棵树,他至少还有父节点,所以w[u]至少还要加上父亲节点所以不可能相等
特判n=2
dp方程,
f[u][0]:以u为子树,选u为好节点的最大个数,且这个最大个数的代价总和最小
那么他的儿子节点只能不是好节点
f[u][1]:以u为子树,不选u为好节点的最大个数,且这个最大个数的代价总和最小
那么他的儿子节点可以为好节点也可以不为好节点
如果为好节点的话,由于他的相邻的点都不能为好节点,那么他相邻的点全填1即可
当前点代价就是出度
方案数直接dfs递归回去每一步决策儿子选哪一步即可
#include<bits/stdc++.h>
using namespace std;
const int N = 3e5+10,mod=998244353;
#define int long long
typedef long long LL;
typedef pair<int, int> PII;
typedef unsigned long long ULL;const long long inf=1e17;
using node=tuple<int,int,int,int>;
int n,m,k;
vector<int> g[N];
PII f[N][2];
int sz[N];
PII lst[N][2];
PII Mx(PII a,PII b)
{if(a.first>b.first) return a;if(b.first>a.first) return b;if(a.second<=b.second)return a;else return b;
}
void dfs(int u,int fa)
{f[u][1]={1,(int)(g[u].size())};f[u][0]={0,1};for(auto v:g[u]){if(v==fa) continue;dfs(v,u);f[u][0].first+=Mx(f[v][1],f[v][0]).first;f[u][0].second+=Mx(f[v][1],f[v][0]).second;f[u][1].first+=f[v][0].first;f[u][1].second+=f[v][0].second;}
}
int ans[N];
void dfs1(int u,int fa,int now)
{if(now==1){ans[u]=g[u].size();}else ans[u]=1;for(auto v:g[u]){if(v==fa) continue;if(now==1){dfs1(v,u,0);}else{if(f[v][0]==Mx(f[v][0],f[v][1])){dfs1(v,u,0);}else dfs1(v,u,1);}}
}
void solve()
{cin>>n;if(n==2){cout<<"2 2\n";cout<<"1 1\n";return ;}for(int i=1;i<n;i++){int a,b;cin>>a>>b;g[a].push_back(b);g[b].push_back(a);}dfs(1,0);auto res=Mx(f[1][0],f[1][1]);cout<<res.first<<" "<<res.second<<"\n";if(res==f[1][0]){dfs1(1,0,0);}else dfs1(1,0,1);for(int i=1;i<=n;i++) cout<<ans[i]<<" ";
}signed main()
{cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);int t=1;//cin>>t;while(t--) solve();
}
E:
这题比较绕以2为例
2^1 2^2 2^3 2的行
2^2 2^3 2^4 4的行
2^3 2^4 2^5 8的行
然后对于2的幂次方的数来说,不同数的个数就是幂次方的不同数
这对于其他底数的幂次方来说也同理
比如如果
1 2 3 4 5
1*2 1*3 1*4 1*5
2*2 2*3 2*4 2*5
即对于每个不同底数的幂次方来说都适用于这个表,
最多有20行这样的表,
可能我不太会表达这个
Codeforces Round #774 (Div. 2) 简训_codeforces 子树点权下放-CSDN博客
可以看看这个E的题解
求出来这个表后,找不同底数的贡献即可
复杂度是调和级数的1e7也可以过
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6+10,mod=998244353;
#define int long long
typedef long long LL;
typedef pair<int, int> PII;
typedef unsigned long long ULL;const long long inf=1e17;
using node=tuple<int,int,int,int>;
int n,m,k;
bool st[N*21];
LL ans[35];
void solve()
{cin>>n>>m;LL cnt=0;for(int i=1;i<20;i++){for(int j=1;j<=m;j++){if(!st[i*j]) cnt++;st[i*j]=1;}ans[i]=cnt;;}LL res=1;memset(st,0,sizeof(st));for(int i=2;i<=n;i++){if(st[i]) continue;int c=0;for(int j=i;j<=n;j*=i) st[j]=true,c++;res+=ans[c];}cout<<res;}signed main()
{cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);int t=1;//cin>>t;while(t--) solve();
}