11/1 NOIP 模拟赛

 

        11.1 NOIP 模拟赛

期望得分:50;实际得分:50;

思路:暴力枚举 + 快速幂

#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;
typedef long long LL;
const int Mod = 1e9 + 7;

int n, m;
LL ans;

LL qpow(LL a, LL b) {
    LL res = 1;
    while (b) {
        if (b & 1) res = res * a % Mod;
        a = a * a % Mod;
        b >>= 1;
    }
    return res;
}

int main() {
    freopen("sum.in","r",stdin);
    freopen("sum.out","w",stdout);
    scanf("%d%d", &n, &m);
    ans += m;
    for (int i = 2; i <= n; ++i) {
        ans += i;
        for (int j = 2; j <= m; ++j) {
            ans = ans + qpow(i, j);
            if (ans >= Mod) ans -= Mod;
        }
    }
    printf("%lld\n", ans);
    fclose(stdin); fclose(stdout);
    return 0;
}
考场代码

正解:等比数列求和公式  

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>

typedef long long i64;

const i64 modulo = i64(1e9) + 7;

int n, m;

i64 power(i64 base, i64 k) {
    i64 res = 1;
    for ( ; k; k >>= 1) {
        if (k & 1) res = (res * base) % modulo;
        base = (base * base) % modulo;
    }
    return res;
}
i64 inv(i64 k) {
    return power(k, modulo - 2);
}

int main(void) {
    freopen("sum.in","r",stdin);
    freopen("sum.out","w",stdout);
    scanf("%d%d", &n, &m);

    i64 ans = m;
    for (int i = 2; i <= n; ++i) {
        i64 t = i;
        t = t * ((power(i, m) - 1 + modulo) % modulo) % modulo;
        t = t * inv(i - 1) % modulo;
        ans = (ans + t) % modulo;
    }

    printf("%d\n", (int) ans);
    fclose(stdin);
    fclose(stdout);


    return 0;
}
View Code

 

       

期望得分:100;实际得分:100;

思路:输入时统计边权和,用边权和的两倍减去距 1 号点最远点的距离,即为最后答案

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <deque>
using namespace std;
const int INF = 0x3f3f3f3f;
const int M = 50005;

int ans;
int n, m, tot;
int dis[M], vis[M];
int to[M*2], net[M*2], head[M], cap[M*2];

void add(int u, int v, int w) {
    to[++tot] = v; net[tot] = head[u]; head[u] = tot; cap[tot] = w;
    to[++tot] = u; net[tot] = head[v]; head[v] = tot; cap[tot] = w;
}

deque<int> Q;
void spfa(int x) {
    for (int i = 1; i <= n; ++i)
        vis[i] = 0, dis[i] = INF;
    vis[x] = 1; dis[x] = 0; Q.push_back(x);
    while (!Q.empty()) {
        int y = Q.front(); Q.pop_front(); vis[y] = 0;
        for (int i = head[y]; i; i = net[i]) {
            int t = to[i];
            if (dis[t] > dis[y] + cap[i]) {
                dis[t] = dis[y] + cap[i];
                if (!vis[t]) {
                    vis[t] = 1;
                    if (Q.empty() || dis[t] > dis[Q.front()]) Q.push_back(t);
                    else Q.push_front(t);
                }
            }
        }
    }
}

int main() {
    freopen("tour.in","r",stdin);
    freopen("tour.out","w",stdout);
    scanf("%d", &n);
    for (int i = 1; i < n; ++i) {
        int u, v, w;
        scanf("%d%d%d", &u, &v, &w);
        add(u, v, w);
        ans += w * 2;
    }
    spfa(1);
    int maxn = 0;
    for (int i = 1; i <= n; ++i)
        maxn = max(maxn, dis[i]);
    printf("%d\n", ans - maxn);
    fclose(stdin); fclose(stdout);
    return 0;
}
考场代码

好像还可以用树形DP做 qwq

放上学姐的代码 Orz

#include<cmath>
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define MAXN 50010
using namespace std;
int n,tot;
int dad[MAXN],sum[MAXN],bns[MAXN],size[MAXN],dp[MAXN];
int to[MAXN*2],cap[MAXN*2],net[MAXN*2],head[MAXN];
int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
void add(int u,int v,int w){
    to[++tot]=v;cap[tot]=w;net[tot]=head[u];head[u]=tot;
}
void dfs(int now){
    size[now]=1;
    for(int i=head[now];i;i=net[i])
        if(dad[now]!=to[i]){
            dad[to[i]]=now;
            dfs(to[i]);
            sum[now]+=sum[to[i]]+cap[i];
            size[now]+=size[to[i]];
        }
}
void pre(int now){
    if(size[now]==1)    dp[now]=0; 
    for(int i=head[now];i;i=net[i])
        if(dad[now]!=to[i])
            pre(to[i]);
}
void work(int now){
    int x;
    for(int i=head[now];i;i=net[i])
        if(dad[now]!=to[i]){
            work(to[i]);
            dp[now]=min(dp[to[i]]+cap[i]+(sum[now]-sum[to[i]]-cap[i])*2,dp[now]);
        }
}
int main(){
    //freopen("lpp.in","r",stdin);
    freopen("tour.in","r",stdin);
    freopen("tour.out","w",stdout);
    n=read();
    for(int i=1;i<n;i++){
        int u=read();
        int v=read();
        int w=read();
        add(u,v,w);add(v,u,w);
    }
    memset(dp,0x7f,sizeof(dp));
    dfs(1);
    pre(1);
    work(1);
    cout<<dp[1]; 
}
View Code

 

 期望得分:0。。。实际么。。。没有分 qwq

思路:暴力搜索,枚举每一个长度等于 K 的子序列并进行判断

 然后。。。没调出来,就gg了。。

#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;
const int M = 100005;

int ans = 1;
int n, k;
int a[M];

void dfs(int now, int tmp, int t1, int t2) {
    if (a[now] == 4 && t1 == 1) return ;
    else if (a[now] == 7 && t2 == 1) return ;
    if (tmp == k) { ++ans; return ; }
    if (a[now] == 4) dfs(now + 1, tmp + 1, t1 + 1, t2);
    else if (a[now] == 7) dfs(now + 1, tmp + 1, t1, t2 + 1);
    else dfs(now + 1, tmp + 1, t1, t2);
}

int main() {
    freopen("lucky.in","r",stdin);
    freopen("lucky.out","w",stdout);
    scanf("%d%d", &n, &k);
    for (int i = 1; i <= n; ++i) {
        scanf("%d", &a[i]);
    }
    for (int i = 1; i <= n - k + 1; ++i) {
        if (a[i] == 4) dfs(i, 1, 1, 0);
        else if (a[i] == 7) dfs(i, 1, 0, 1);
        else dfs(i, 1, 0, 0);
    }
    printf("%d\n", ans);
    fclose(stdin); fclose(stdout);
    return 0;
}
考场代码

正解:DP + 组合数

#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <iostream>
#include <vector>
#include <map>

using std::min;
using std::max;

typedef long long i64;
const i64 modulo = i64(1e9) + 7;
const int MaxN = 100005;
const int MaxM = 1024;

i64 power(i64 base, i64 k) {
    i64 res = 1;
    for ( ; k; k >>= 1) {
        if (k & 1) res = (res * base) % modulo;
        base = (base * base) % modulo;
    }
    return res;
}

i64 inv(i64 k) {
    return power(k, modulo - 2);
}

std::vector<i64> gen_lucky(i64 upper) {
    std::vector<i64> res; res.clear();
    std::vector<i64> a; a.clear(); a.push_back(0);
    for (int i = 0; i < 10; ++i) {
        std::vector<i64> b; b.clear();
        for (size_t j = 0; j < a.size(); ++j) {
            b.push_back(a[j] * 10 + 4);
            b.push_back(a[j] * 10 + 7);
        }
        if (b[0] < upper) {
            res.insert(res.end(), b.begin(), b.end());
            a = b;
        } else {
            return res;
        }
    }
    return res;
}

std::vector<i64> lucky;
std::map<i64, int> lucky2idx;
int n, m, unlucky, k, a[MaxN], cnt[MaxM];
i64 dp[MaxM][MaxM];
i64 f[MaxN];

i64 bincoef(int a, int b) {
    i64 tmp = f[a];
    tmp = tmp * inv(f[b]) % modulo;
    tmp = tmp * inv(f[a-b]) % modulo;
    return tmp;
}

int main(void) 
{   freopen("lucky.in","r",stdin);
    freopen("lucky.out","w",stdout);
    lucky = gen_lucky(1e9);
    m = lucky.size();
    for (int i = 0; i < m; ++i) {
        lucky2idx[lucky[i]] = i;
    }

    scanf("%d%d", &n, &k);
    unlucky = n;
    for (int i = 0; i < n; ++i) {
        scanf("%d", a+i);
        std::map<i64, int>::iterator it = lucky2idx.find(a[i]);
        if (it != lucky2idx.end()) ++cnt[it->second], --unlucky;
    }

    dp[0][0] = 1;
    for (int i = 0; i < m; ++i) {
        for (int j = 0; j <= i; ++j) {
            dp[i+1][j] = (dp[i+1][j] + dp[i][j]) % modulo;
            dp[i+1][j+1] += (dp[i+1][j+1] + (dp[i][j] * cnt[i] % modulo)) % modulo;
        }
    }

    f[0] = 1;
    for (int i = 1; i <= n; ++i) {
        f[i] = f[i-1] * i % modulo;
    }

    i64 ans = 0;
    int st = max(0, k-m);
    int ed = min(k, unlucky);
    for (int i = st; i <= ed; ++i) {
        ans += dp[m][k-i] * bincoef(unlucky, i) % modulo;
        ans %= modulo;
    }

    printf("%d\n", (int) ans);
    fclose(stdin);
    fclose(stdout);

    return 0;
}
View Code

 

posted @ 2018-11-01 16:17  落云小师妹  阅读(224)  评论(2编辑  收藏  举报