220803 总结

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;
}
posted @ 2022-08-03 23:15  Burnling  阅读(38)  评论(0编辑  收藏  举报