喵哈哈村的魔法考试 Round #11 (Div.2) 题解

喵哈哈村的星星与月亮(一)

打表发现答案就等于a*b%mod

注意a*b可能爆longlong

#include<bits/stdc++.h>
using namespace std;
const int mod = 1e9+7;

int main(){
    long long a,b,c;
    while(cin>>a>>b>>c){
    cout<<((a%mod)*(b%mod))%mod<<endl;
    }
}

喵哈哈村的星星与月亮(二)

数据范围只有10,所以直接dfs就好了。

直接枚举每个点的颜色,然后O(m)去check就好了。

理论复杂度最大是n^n*m,但实际上不会这么大。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 25;
int n,m,mp[maxn][maxn],Mx=0;
int ty[maxn];
vector<int> E[maxn],P;
int FF = 0;
vector<int> D;
int ti = 0;
int vis[maxn];
int T = 0;
void dfs2(int x,int y){
    if(FF)return;
    if(x==n+1){
        FF = 1;
        return;
    }
    for(int i=1;i<=min(x,y);i++){
        ty[x]=i;
        int flag = 0;
        for(int j=1;j<x;j++){
            if(mp[x][j]==1&&ty[x]==ty[j]){
                flag = 1;
                break;
            }
        }
        if(flag == 0)
            dfs2(x+1,y);
    }
}
int main(){
    srand(772003);
    while(scanf("%d%d",&n,&m)!=EOF){
        memset(mp,0,sizeof(mp));
        for(int i=0;i<maxn;i++)E[i].clear();
        for(int i=1;i<=m;i++){
            int a,b;
            scanf("%d%d",&a,&b);
            E[a].push_back(b);
            E[b].push_back(a);
            mp[a][b]=1;
            mp[b][a]=1;
        }
        Mx = 1;
        int l = 1,r = n;
        int ans = n;
        for(int i=Mx;i<=n;i++){
            ti = 0;
            FF = 0;
            dfs2(1,i);
            if(FF){
                cout<<i<<endl;
                break;
            }
        }
    }
}

喵哈哈村的星星与月亮(三)

这道题实际上和[BZOJ 4004][JLOI2015]装备购买 一模一样。

将wi排序,然后从大到小插入就好了,如果插入还是线性无关的就插入,否则就不插入。

用拟阵可以证明贪心的正确性。

然后我们用高斯消元来判断是否线性无关即可。

#include <bits/stdc++.h>
#define maxn 510
using namespace std;
typedef long long ll;
//const int mod = 998224353;
int mod;
struct Node{
    int a[maxn], c;
    bool operator<(const Node& k)const{return c > k.c;}
}p[maxn], bases[maxn];
bool bases_flag[maxn];
int n, m;

ll power_mod(ll a, ll b, ll mod){
    ll ret = 1;
    while(b){
        if(b & 1)ret = ret * a % mod;
        b >>= 1;
        a = a * a % mod;
    }return ret;
}

void Gauss(Node& a, const Node& b, int o){
    //t = a.a[o] / b.b[o]
    ll t = mod - a.a[o] * power_mod(b.a[o], mod-2, mod) % mod;
    for(int i = o; i <= m; i ++)
        a.a[i] =(a.a[i] + b.a[i] * t) % mod;
}

bool Insert(int pos){
    for(int i = 1; i <= m; i ++){
        if(p[pos].a[i]){
            if(!bases_flag[i]){
                bases[i] = p[pos];
                bases_flag[i] = true;
                return true;
            }
            Gauss(p[pos], bases[i], i);
        }
    }
    return false;
}

int main(){
    while(scanf("%d%d%d", &n, &m, &mod)!=EOF){
        memset(bases,0,sizeof(bases));
        memset(bases_flag,0,sizeof(bases_flag));
        for(int i = 1; i <= n; i ++){
            for(int j = 1; j <= m; j ++)
                scanf("%d", &p[i].a[j]);
            scanf("%d", &p[i].c);
        }

        sort(p+1, p+1+n);

        long long ans = 0;
        for(int i = 1; i <= n; i ++)
            if(Insert(i))ans += p[i].c;
        printf("%lld\n", ans);
    }
    return 0;
}

喵哈哈村的星星与月亮(四)

假设三个数能够构成等比数列的话,那么满足:

ac=bb,满足 a<b,b<c(都相同的另外考虑)

我们发现其实b的因子个数只有logn个,那么b^2的因子个数,实际上也不会很多,所以我们直接暴力的把b*b且小于b的因子个数暴力dfs出来就好了。

然后我们枚举b就可以算答案了。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6+7;
int a[maxn];
int num[100005],n;
vector<int> E[maxn],P[maxn],N[maxn];
void dfs(int x,int st,int Num){
    E[x].push_back(Num);
    for(int j=st;j<P[x].size();j++){
        int now = Num;
        for(int k=1;k<=N[x][j]*2;k++){
            now*=P[x][j];
            if(now>x)break;
            dfs(x,j+1,now);
        }
    }
}
int main(){
    for(int i=1;i<=100000;i++){
        int x = i;
        for(int j=2;j*j<=i;j++){
            if(x%j==0){
                P[i].push_back(j);
                N[i].push_back(0);
                while(x%j==0){
                    N[i][N[i].size()-1]++;
                    x/=j;
                }
            }
        }
        if(x!=1){
            P[i].push_back(x);
            N[i].push_back(1);
        }
        dfs(i,0,1);
        sort(E[i].begin(),E[i].end());
        E[i].erase(unique(E[i].begin(),E[i].end()),E[i].end());
    }
    while(scanf("%d",&n)!=EOF){
        memset(num,0,sizeof(num));
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            num[a[i]]++;
        }
        long long ans = 0;
        for(int i=1;i<=100000;i++){
            if(num[i]>=3){
                ans = ans + 1ll*(num[i]-2)*(num[i]-1)*num[i]/6LL;
            }
            for(int j=0;j<E[i].size();j++){
                if(i==E[i][j])continue;
                if(1ll*i*i%E[i][j]!=0)continue;
                if(1ll*i*i/E[i][j]<=100000){
                    int p = 1ll*i*i/E[i][j];
                    ans = ans + 1ll * num[i]*num[E[i][j]]*num[p];
                }
            }
        }
        cout<<ans<<endl;
    }
}

喵哈哈村的星星与月亮(五)

这道题是离线树状数组。

询问,如果只有A数组的话,实际上就是权值线段树或者主席树的裸题了。

那么我们其实只要将询问按照A数组从小到大排序,然后依次删除对于>A不合法的,然后用个权值树状数组去查询,就可以了。

细节比较多,所以还是看代码吧。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+7;
int n,q,d[maxn],ans[maxn],All=0;
struct node{
    int first,second;
}a[maxn];
bool cmp(node A,node B){
    return A.first<B.first;
}
struct Node{
    int first,secondfirst,secondsecond;
}query[maxn];
bool cmp2(Node A,Node B){
    return A.first<B.first;
}
inline bool scan_d(int &num)
{
        char in;bool IsN=false;
        in=getchar();
        if(in==EOF) return false;
        while(in!='-'&&(in<'0'||in>'9')) in=getchar();
        if(in=='-'){ IsN=true;num=0;}
        else num=in-'0';
        while(in=getchar(),in>='0'&&in<='9'){
                num*=10,num+=in-'0';
        }
        if(IsN) num=-num;
        return true;
}
int lowbit(int x){
    return x&(-x);
}
void update(int x,int v){
    for(int i=x;i<maxn;i+=lowbit(i)){
        d[i]+=v;
    }
}
int getsum(int x){
    int ans = 0;
    for(int i=x;i;i-=lowbit(i))
        ans+=d[i];
    return ans;
}
int main(){;
    while(scanf("%d%d",&n,&q)!=EOF){
        memset(d,0,sizeof(d));
        memset(ans,0,sizeof(ans));
        All=0;
        for(int i=1;i<=n;i++)
            scan_d(a[i].first);
        for(int i=1;i<=n;i++){
            scan_d(a[i].second);
            All++;
            update(a[i].second,1);
        }
        for(int i=1;i<=q;i++){
            scan_d(query[i].first);
            scan_d(query[i].secondfirst);
            query[i].secondsecond=i;
        }
        sort(a+1,a+1+n,cmp);
        sort(query+1,query+1+q,cmp2);
        int tot = 1;
        for(int i=1;i<=q;i++){
            while(tot<=n&&a[tot].first<query[i].first){
                update(a[tot].second,-1);
                All--;
                tot++;
            }
            ans[query[i].secondsecond]=All-getsum(query[i].secondfirst-1);
        }
        for(int i=1;i<=q;i++){
            printf("%d\n",ans[i]);
        }
    }
    return 0;
}
posted @ 2017-04-04 19:33  qscqesze  阅读(445)  评论(0编辑  收藏  举报