【LGR-050】洛谷8月月赛

只有比赛现场的暴力代码留念,复盘题解见具体题目

T1 耗时20mins,暴力枚举,复杂度O(nQ),期望得分50

#include<iostream>
#include<algorithm>
using namespace std;

#define mod 998244353
const int maxn = 1e6+10;
typedef long long LL;

LL n, a[2010][maxn], len;//第i次操作后j的值,已经操作了几次
void change(int x){
    for(int i = len+1; i <= x; i++)
        for(int j = 1; j <= n; j++)
            a[i][j] = a[i-1][j]+a[i-1][j%n+1];
}

int main(){
    cin>>n;
    for(int i = 1; i <= n; i++)cin>>a[0][i];
    int Q;  cin>>Q;
    for(int i = 1; i <= Q; i++){
        int x, y;  cin>>x>>y;
        if(x > len)change(x);
        cout<<(a[x][y]%mod)<<'\n';
    }
    return 0;
}

T2 耗时20mins

  • 给定一个序列
  • 每次可以合并两个数得到一个新数,结果为较小的数的两倍
  • 任意次操作后,能得到的最大数是多少。

贪心,每次选最小的两个合并,,我也不知道为什么这样,只是隐隐感觉。。。可是明明样例都过了啊。期望得分0 or 60

#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
const int maxn = 1e7+10;

int n, m, seed, a[maxn];
priority_queue<int, vector<int>, greater<int> >q;
void generate_array(int a[], int n, int m, int seed) {
    unsigned x = seed;
    for (int i = 0; i < n; ++i) {
        x ^= x << 13;
        x ^= x >> 17;
        x ^= x << 5;
        //a[i] = x % m + 1;
        q.push(x%m+1);
    }
}

int main(){
    cin>>n>>m>>seed;
    generate_array(a,n,m,seed);
    while(q.size()!=1){
        int a = q.top();  q.pop();
        int b = q.top();  q.pop();
        int t = 2*min(a,b);
        q.push(t);
    }
    cout<<q.top()<<'\n';
    return 0;
}

T3

没看懂题+没什么想法。耗时10mins,输出2,期望得分0

#include<iostream>
using namespace std;
int main(){
    cout<<2<<'\n';
    return 0;
}

T4

  • 在n行m列的棋盘上放2*n个炮,让他们互不攻击
  • 求方案数

我不知道炮的攻击是不是同行隔着一个棋子的。。。

所以也就是每行每列最多放2个?枚举每个状态,判断列是否攻击(个数大于2剪枝剪掉),复杂度好像O(nCm2logn) ,也许会小一点。,期望得分20。耗时40mins

#include<iostream>
#include<bitset>
#include<map>
using namespace std;
#define mod 998244353
const int maxn = 100010;
int n, m, ans;
map<int, bitset<10010> >c; int num[maxn];//第i列有几个炮
void dfs(int cur){
    if(cur == n){
        ans = (ans+1)%mod;
        return ;
    }
    for(int i = 0; i < m; i++){//枚举所有状态
        for(int j = 0; j < i; j++){//都到m的话,i<j一次,j<i一次就会有重复,且满足行条件i!=j
            //c[cur] = (1<<i)|(1<<j);
            bitset<10010>s; s[i]=1; s[j]=1;  c[cur] = s;
            num[i]++, num[j]++;
            if(num[i]<=2&&num[j]<=2)dfs(cur+1);//可行性剪枝
            num[i]--, num[j]--;
        }
    }
}
int main(){
    cin>>n>>m;
    dfs(0);
    cout<<ans<<'\n';
    return 0;
}

整个:
耗时1h30mins,最后1h直接弃坑(貌似一开始就没打算写标程?)。
期望得分50+30+0+20 = 100。。。

实际得分0+20+0+20=40。。。

posted @ 2018-08-03 10:52  gwj1139177410  阅读(212)  评论(0编辑  收藏  举报
选择