A 很简单的贪心
#include <bits/stdc++.h>
using namespace std;
const int maxn=105;
int num[maxn];
int main(int argc, char const *argv[])
{
int k,n;
while(cin>>n>>k){
int sum=0;
for(int i=0;i<n;i++){
cin>>num[i];
sum+=num[i];
}
if(sum<k){
printf("-1\n");
}
else{
int ans=0,cnt=0,temp=0;
for(int i=0;i<n;i++){
int t=min(num[i]+temp,8);
temp=num[i]+temp-t;
cnt+=t,ans++;
if(cnt>=k) break;
}
if(cnt<k) ans=-1;
printf("%d\n",ans);
}
}
return 0;
}
看来以后紫名,蓝名出的题少打
#include "bits/stdc++.h"
using namespace std;
int main(){
int n,k,i,s=0,c=0;
cin>>n>>k;
int a[k];
for(i=0;i<k;i++){
cin>>a[i];
if(a[i]%2!=0){
a[i]++;
c++;
}s+=a[i];
}
if(s>8*n)cout<<"NO";
else if(s==8*n){
if(k==4*n&&c<n)cout<<"NO";
else cout<<"YES";
}
else cout<<"YES";
return 0;
}
C
dfs一遍即可
唯一要注意的是,每次分叉的时候都有一个概率,处理一下就好,最后的期望是加权平均数来的。
#include <bits/stdc++.h>
using namespace std;
const int maxn=100005;
vector<int>edge[maxn];
int dis[maxn];
double p[maxn];
bool vis[maxn],en[maxn];
inline void add_edge(int a,int b){
edge[a].push_back(b);
edge[b].push_back(a);
}
void dfs(int u,int fa){
vis[u]=1;
int flag=0;
int len=edge[u].size();
for(int i=0;i<len;i++){
int v=edge[u][i];
if(!vis[v]){
flag=1;
dis[v]=dis[u]+1;
if(u!=1) p[v]=p[u]/((len-1)*1.0);
else p[v]=p[u]/(len*1.0);
dfs(v,u);
}
}
if(!flag){
en[u]=1;
}
}
int main(int argc, char const *argv[])
{
int n;
while(cin>>n){
int a,b;
for(int i=1;i<=n;i++){
edge[i].clear();
}
for(int i=0;i<n-1;i++){
cin>>a>>b;
add_edge(a,b);
}
memset(vis,0,sizeof(vis));
memset(en,0,sizeof(en));
memset(dis,0,sizeof(dis));
p[1]=1.0;
dfs(1,0);
double ans=0;
for(int i=1;i<=n;i++){
if(en[i]){
double temp=(dis[i]*1.0)*p[i];
ans+=temp;
}
}
printf("%.15f\n",ans);
}
return 0;
}
D
枚举GCD+容斥
一遇到这种数学题就不会了,看来我离紫名什么的还很远啊。。。
不过现在终于学会了
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const ll maxn=1000010;
ll p[maxn],cnt[maxn],f[maxn];
int main(int argc, char const *argv[])
{
ll n;
p[0]=1;
for(ll i=1;i<maxn;i++){
p[i]=(p[i-1]*2)%mod;
}
cin.sync_with_stdio(false);
cin>>n;
ll Max=0,temp;
for(ll i=0;i<n;i++){
cin>>temp;
cnt[temp]++;
Max=max(Max,temp);
}
ll ans=0;
for(ll i=Max;i>1;i--){
ll t=0;
for(ll j=i;j<=Max;j+=i){
t+=cnt[j];
}
if(t){
f[i]=(1LL*t*p[t-1])%mod;
for(ll j=i+i;j<maxn;j+=i){
f[i]=(f[i]-f[j]+mod)%mod;
}
ans=(1LL*f[i]*i+ans)%mod;
}
}
cout<<ans<<endl;
return 0;
}
E Mother of Dragons
一个最大团算法,就当是一道理解最大团born算法的题好了
这个写法是优化过的,先当作一个模板好了。
#include <bits/stdc++.h>
using namespace std;
const int maxn=50;
typedef long long ll;
ll g[maxn];
int ans,n;
// #define ctz(x) ((x)? __builtin_ctzll(x):64)
inline int ctz(ll s){
return s?__builtin_ctzll(s):8*sizeof(ll);
}
void BronKerbosch(ll clique,ll allow,ll forbid){
if(!allow && !forbid){
ans = max(ans,__builtin_popcountll(clique));return;
}
if(!allow)return;
int pivot = ctz(allow | forbid);//选择轴点
ll choose = allow & ~g[pivot];
for(int u = ctz(choose) ; u<n ; u += ctz(choose>>(u+1))+1){
BronKerbosch(clique|(1LL<<u),allow&g[u],forbid&g[u]);
allow ^=1LL<<u;
forbid|=1LL<<u;
}
}
int main(int argc, char const *argv[])
{
ios_base::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
int k;
ll x;
cin>>n>>k;
memset(g,0,sizeof(g));
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
cin>>x;
g[i]^=(x<<j);//build the graph
}
}
BronKerbosch(0LL,(1LL<<n)-1,0LL);
printf("%.9f\n",1.0*k*k*(ans-1)/(2*ans));
return 0;
}