ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

220803 总结

2022-08-03 23:33:09  阅读:155  来源: 互联网

标签:总结 name int 220803 double maxN ans inline


220803 总结

总之就是挂大分

顺序开题

T1 解方程:意料之中,没想到可以边读入边取模。

T2 三角形:明明暴力能拿 \(40\) 分,非要人类智慧乱搞,痛失 \(20\) 分

T3 游戏(屠龙勇士):屠龙勇士反被龙屠考场上推出来式子了但是忘了 \(x\) 前面有系数该怎么解于是去打暴力,盯着 \(p=1\) 的 \(30\) 分去的,又由于没想到剑的攻击力可以重复,开的 set 没开 multiset 痛失 \(10\) 分

T4 找朋友:不知道怎么回事反正输出全是零(

T1 解方程

P2312 [NOIP2014 提高组] 解方程

因为 \(N,M\) 范围都很小,所以完全可以在 \([1,M]\) 的区间内将所有的正整数 \(x\) 代入方程看结果是否为 \(0\)

问题出在离谱的 \(|a_i|\leq10^{10000}\) 上,但是因为最后只需要判断结果是否为 \(0\) 即可,所以可以在模意义下做这题

#include<bits/stdc++.h>
using namespace std;

#define FO(name) freopen(name".in","r",stdin);freopen(name".out","w",stdout)

const int maxN = 1e6+10;
typedef long long ll;

int N,M;
ll A[maxN];
int Ans[maxN];

const int MOD = 998244353;

inline bool clc(ll x){
	int ans = 0;
	for(int i = N;i>=1;i--){
		ans = ((ans + A[i]) * x) % MOD;
	}
	ans = (ans + A[0]) % MOD;
	return ans == 0;
}

inline ll read(){
	ll x=0;int f=1;char c=getchar();
	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
	while(isdigit(c)){x=(x<<3)+(x<<1)+(c^48);x=x%MOD;c=getchar();}
	return x*f;
}

int cnt;

int main(){

	scanf("%d%d",&N,&M);
	for(int i = 0;i<=N;i++) A[i] = read();
	for(int i = 1;i<=M;i++){
		if(clc(i)) Ans[++cnt] = i;
	}
	printf("%d\n",cnt);
	for(int i = 1;i<=cnt;i++) printf("%d\n",Ans[i]);
	return 0;
}

T2 三角形

P4423 [BJWC2011] 最小三角形

平面分治,可惜我不会写

人类智慧,玄学旋转,转两次更保险。

#include<bits/stdc++.h>
using namespace std;

#define FO(name) freopen(name".in","r",stdin);freopen(name".out","w",stdout)
//#define double long double

typedef long long ll;

const int maxN = 1e6+10;

struct Point{
	double x,y;
	Point(){};
	Point(int x,int y):x((double)x),y((double)y){};
	friend bool operator < (Point A,Point B){
		if(A.x != B.x) return A.x < B.x;
        return A.y < B.y;
	}
}P[maxN];

inline double Q2p(double x){
	return x*x;
}

inline double dis(Point A,Point B){
	double t =  sqrt(Q2p(A.x-B.x)+Q2p(A.y-B.y));
	return t;
}

inline double C(int a,int b,int c){
	return dis(P[a],P[b])+dis(P[a],P[c])+dis(P[b],P[c]);
}

double ans = 1e18;

int N;

void Turn(int D){
    for(int i = 1;i<=N;i++){
        double x = P[i].x;
        double y = P[i].y;
        P[i].x = cos(D)*x-sin(D)*y;
        P[i].y = sin(D)*x+cos(D)*y;
    }
    sort(P+1,P+1+N);
    for(int i = 1;i<N-1;i++){
        for(int j = i+1;j<min(i+10,N);j++){
            for(int k = j+1;k<=min(j + 10,N);k++){
                ans = min(ans,C(i,j,k));
            }
        }
    }
}
int main(){

    srand(time(0));
	scanf("%d",&N);
	for(int i = 1;i<=N;i++){
		scanf("%lf%lf",&P[i].x,&P[i].y);
	}

	Turn(rand()%360);
    Turn(rand()%360);
	printf("%.6lf\n",ans);
	return 0;
}

T3 游戏

P4774 [NOI2018] 屠龙勇士

multiset 存剑的攻击力,可以得到杀每条龙用的剑的攻击力序列 \(S\)。

解一个同余方程组,类似

\(\left\{\begin{matrix} xS_1 \equiv A_1 \pmod {p_1} \\ xS_2 \equiv A_2 \pmod {p_2} \\ xS_3 \equiv A_3 \pmod {p_3} \\ \vdots \\ xS_n \equiv A_n \pmod {p_n} \end{matrix}\right.\)

如果 \(S_i=1\) 的话,可以直接用 exgcd 求解。

设前 \(i-1\) 组方程的解为 \(ans\) ,\(M=\operatorname{lcm}(p_1,p_2,\dots,p_n)\) 。

那么前 \(i\) 组同余方程的解需要满足 \(S_i(ans+Mx)\equiv A_i \pmod{p_i}\)

移项得 \(S_iMx\equiv A_i-S_i\cdot ans \pmod {p_i}\)

用 exgcd 求解 \((S_iM)x+(p_i)y=(A_i-S_i\cdot ans)\)

#include<bits/stdc++.h>
using namespace std;

#define int long long

const int maxN = 1e5 + 10;

#define FO(name) freopen(name".in","r",stdin);freopen(name".out","w",stdout)

inline int read() {
    int x = 0, f = 1;
    char c = getchar();
    while (!isdigit(c)) {
        if (c == '-')f = -1;
        c = getchar();
    }
    while (isdigit(c)) {
        x = (x << 3) + (x << 1) + (c ^ 48);
        c = getchar();
    }
    return x * f;
}

multiset<int> Sw;
int N, M;
int A[maxN];
int P[maxN];
int S[maxN];
int T[maxN];

inline void input() {
    Sw.clear();

    scanf("%lld%lld", &N, &M);
    for (int i = 1; i <= N; i++) A[i] = read();
    for (int i = 1; i <= N; i++) P[i] = read();
    for (int i = 1; i <= N; i++) T[i] = read();
    for (int i = 1; i <= M; i++) {
        int t = read();
        Sw.insert(t);
    }
    for (int i = 1; i <= N; i++) {
        auto p = Sw.upper_bound(A[i]);
        p--;
        if (p == Sw.begin()) {
            p = Sw.lower_bound(0);
            S[i] = *p;
            Sw.erase(p);
        } else {
            S[i] = *p;
            Sw.erase(p++);
        }
        Sw.insert(T[i]);
    }
    //  for(int i = 1;i<=N;i++) printf("%d ",S[i]);
    //  printf("\n");
}

inline void exgcd(int a, int b, int &g, int &x, int &y) {
    if (b == 0) g = a, x = 1, y = 0;
    else {
        exgcd(b, a % b, g, x, y);
        int t = x;
        x = y;
        y = t - (a / b) * y;
    }
}

int ma = -1;

int exCRT() {
    int ans = 0, lcm = 1;
    int x, y, g, ATK, B, C;
    for (int i = 1; i <= N; i++) {
        ATK = (__int128)S[i] * lcm % P[i];
        B = P[i];
        C = (A[i] - S[i] * ans % P[i] + P[i]) % P[i];
        exgcd(ATK, B, g, x, y);
        x = (x % B + B) % B;
        if (C % g) return -1;
        ans += (__int128)(C / g) * x % (B / g) * lcm % (lcm *= (B / g));
        ans %= lcm;
    }
    if (ans < ma) ans += ((ma - ans - 1) / lcm + 1) / lcm;
    return ans;
}
inline bool TP1() {
    for (int i = 1; i <= N; i++) if (P[i] != 1) return false;
    return true;
}

inline int quickPow(int a, int b, int p) {
    int ans = 1;
    while (b) {
        if (b & 1) ans = ans * a % p;
        a = a * a % p;
        b >>= 1;
    }
    return ans;
}

inline int CRT() {
    int M = 1;
    for (int i = 1; i <= N; i++) {
        M *= P[i];
    }
    int ans = 0;
    for (int i = 1; i <= N; i++) {
        int M1 = quickPow(M, P[i] - 2, P[i]);
        ans = (ans + A[i] * M * M1) % P[i];
    }
    return 0;
    //  return ans * ;
}

inline void solve() {
    input();
    ma = -1;
    for (int i = 1; i <= N; i++) {
        ma = max(ma, (int)(ceil(1.0 * A[i] / S[i])));
    }
    if(TP1()){
        printf("%lld\n",ma);
        return;
    }
    printf("%lld\n", exCRT());
}
signed main() {
    int T;
    scanf("%lld", &T);
    while (T--) {
        solve();
    }
    return 0;
}

T4 找朋友

P7738 [NOI2021] 量子通信

跟输入杠了一个多点最后发现把 charint 搁那移位,乐死我了

一旦输入写对了基本就能对了,但是会 TLE

暴力思路就是对每个新生算一遍所有人与他的友好度最后输出。

但是由于 \(k \leq 15\) ,如果我们用 \(16\) 个 \(16\) 位整数来存储 DNA 的话,至少会有一段 DNA 是完全相同的。

用一个 vector 表示第 \(i\) 组 DNA 片段 为 \(j\) 的学生的编号。

对于每个转校生,先看 \(16\) 组片段分别与哪些学生相同,再去计算友好值

然后就是卡常乐

函数前 inline ,快读,循环展开,优先使用位运算,用 __builtin_popcount(a^b) 计算相似度,const 定义常量等

#include<bits/stdc++.h>
using namespace std;

typedef unsigned long long ull;
const int maxN = 400000;
bool s[maxN + 1][256];

#define FO(name) freopen(name".in","r",stdin);freopen(name".out","w",stdout)

int lastans = 0;

inline ull myRand(ull &k1, ull &k2) {
    ull k3 = k1, k4 = k2;
    k1 = k4;
    k3 ^= (k3 << 23);
    k2 = k3 ^ k4 ^ (k3 >> 17) ^ (k4 >> 26);
    return k2 + k4;
}

inline void gen(int n, ull a1, ull a2) {
    for (int i = 1; i <= n; i++)
        for (int j = 0; j < 256; j++)
            s[i][j] = (myRand(a1, a2) & (1ull << 32)) ? 1 : 0;
}

bool s2[maxN+2];
int N, Q;
ull a1, a2;
int k;

int M[maxN+2][20];

int T[maxN+2];

const int TSY = 256*256+10;
vector<int> V[17][TSY];

inline int toInt(char c) {
    return isdigit(c) ? c - '0' : c - 'A' + 10;
}

inline int read() {
    char c = getchar();
    while (!isdigit(c)) {
        if (c >= 'A' && c <= 'Z') return c - 'A' + 10;
        c = getchar();
    }
    while (isdigit(c)) return c - '0';
}

inline void printInBin(int x, char endline = '\n') {
    for (int i = 15; i >= 0; i--) {
        putchar((x & (1 << i)) ? '1' : '0');
    }
    if (endline) putchar(endline);
}

int popcount(int x) {

    int cnt = 0;
    for (int i = 0; i < 16; i++) {
        cnt = cnt + (((1 << i) & x) ? 1 : 0);
    }

    return cnt;
}

int a, b, c, d;
int main() {
    //  getM();
    scanf("%d%d%llu%llu", &N, &Q, &a1, &a2);
    gen(N, a1, a2);
    
//    for(int i = 0;i<16;i++){
//        for(int j = 0;j<(1<<16);j++){
//            V[i][j].resize(32);
//        }
//    }
    
    int p = 0;
    for (register int i = 1; i <= N; i++) {
        p = 0;

        for (int j = 0; j < 16; j++) {
            for (int k = 15; k >= 0; k--) {
                M[i][j] |= s[i][p++] ? (1 << k) : 0;
            }
            V[j][M[i][j]].push_back(i);
        }

    }


    while (Q--) {

        for (int i = 0; i < 16; i += 8) {

            T[i] = 0;
            a = read();
            b = read();
            c = read();
            d = read();
            T[i] = (a << 12) + (b << 8) + (c << 4) + d;
            if (lastans)T[i] = ~(T[i] | (~((1 << 16) - 1)));

            T[i + 1] = 0;
            a = read();
            b = read();
            c = read();
            d = read();
            T[i + 1] = (a << 12) + (b << 8) + (c << 4) + d;
            if (lastans)T[i + 1] = ~(T[i + 1] | (~((1 << 16) - 1)));

            T[i + 2] = 0;
            a = read();
            b = read();
            c = read();
            d = read();
            T[i + 2] = (a << 12) + (b << 8) + (c << 4) + d;
            if (lastans)T[i + 2] = ~(T[i + 2] | (~((1 << 16) - 1)));

            T[i + 3] = 0;
            a = read();
            b = read();
            c = read();
            d = read();
            T[i + 3] = (a << 12) + (b << 8) + (c << 4) + d;
            if (lastans)T[i + 3] = ~(T[i + 3] | (~((1 << 16) - 1)));
            
            T[i + 4] = 0;
            a = read();
            b = read();
            c = read();
            d = read();
            T[i + 4] = (a << 12) + (b << 8) + (c << 4) + d;
            if (lastans)T[i + 4] = ~(T[i + 4] | (~((1 << 16) - 1)));
            
            T[i + 5] = 0;
            a = read();
            b = read();
            c = read();
            d = read();
            T[i + 5] = (a << 12) + (b << 8) + (c << 4) + d;
            if (lastans)T[i + 5] = ~(T[i + 5] | (~((1 << 16) - 1)));
            
            T[i + 6] = 0;
            a = read();
            b = read();
            c = read();
            d = read();
            T[i + 6] = (a << 12) + (b << 8) + (c << 4) + d;
            if (lastans)T[i + 6] = ~(T[i + 6] | (~((1 << 16) - 1)));
            
            T[i + 7] = 0;
            a = read();
            b = read();
            c = read();
            d = read();
            T[i + 7] = (a << 12) + (b << 8) + (c << 4) + d;
            if (lastans)T[i + 7] = ~(T[i + 7] | (~((1 << 16) - 1)));
        }

        int k;
        scanf("%d", &k);
        bool flg = false;
//        for (int i = 0; i < 16; i++) {
//            if (V[i][T[i]].size()) {
//                AT = i;
//                siz = V[i][T[i]].size();
//                break;
//            }
//        }
//        if(AT == -1) goto awa;

        for (int i = 0; i < 15; i++) {
            for (int t : V[i][T[i]]) {
                int cnt = 0;
                for (register int j = 0; j < 16; j++) {
                    cnt += __builtin_popcount(M[t][j] ^ T[j]);
                    if(cnt > k) break;
                }

                if (cnt <= k) {
                    printf("1\n");
                    flg = true;
                    lastans = 1;
                    goto qwq;
                }

            }

        }qwq:{};
        if (flg) continue;
        lastans = 0;
        printf("0\n");
    }
    return 0;
}

标签:总结,name,int,220803,double,maxN,ans,inline
来源: https://www.cnblogs.com/burnling/p/16549074.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有