Wannafly挑战赛22游记

Wannafly挑战赛22游记

幸福的人都是相似的,不幸的人各有各的不幸。

——题记

A-计数器

题目大意:

有一个计数器,计数器的初始值为\(0\),每次操作你可以把计数器的值加上\(a_1,a_2,\ldots,a_n\)中的任意一个整数,操作次数不限(可以为\(0\)次),问计数器的值对\(m\)取模后有几种可能。

思路:

由裴蜀定理易得,答案即为\(\frac m{\gcd(m,a_1,a_2,\ldots,a_n)}\)。

源代码:

#include<cstdio>
#include<cctype>
#include<algorithm>
inline int getint() {
    register char ch;
    while(!isdigit(ch=getchar()));
    register int x=ch^'0';
    while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
    return x;
}
const int N=101;
int a[N];
int main() {
    const int n=getint(),m=getint();
    int gcd=m;
    for(register int i=1;i<=n;i++) {
        a[i]=getint()%m;
        gcd=std::__gcd(gcd,a[i]);
    }
    printf("%d\n",m/gcd);
    return 0;
}

B-字符路径

题目大意:

给一个含\(n\)个点\(m\)条边的有向无环图(允许重边,点用\(1\)到\(n\)的整数表示),每条边上有一个字符,问图上有几条路径满足路径上经过的边上的字符组成的的字符串去掉空格后以大写字母开头,句号‘.‘结尾,中间都是小写字母,小写字母可以为\(0\)个。

思路:

拓扑序上DP,记录每个点可以对应多少个大写字母开头的字符串,若在前面加上空格有多少种方案,在后面加上空格有多少种方案(反图)。若当前边为‘.‘则计算对答案的贡献。

源代码:

#include<queue>
#include<cstdio>
#include<cctype>
#include<vector>
inline int getint() {
    register char ch;
    while(!isdigit(ch=getchar()));
    register int x=ch^'0';
    while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
    return x;
}
inline int getch() {
    register char ch=getchar();
    while(!isalpha(ch)&&ch!='_'&&ch!='.') ch=getchar();
    return ch;
}
const int N=5e4+1;
struct Edge {
    int to;
    char w;
};
std::vector<Edge> e[N],e2[N];
inline void add_edge(const int &u,const int &v,const char &w) {
    e[u].push_back((Edge){v,w});
}
inline void add_edge2(const int &u,const int &v,const char &w) {
    e2[u].push_back((Edge){v,w});
}
int n,m,ind[N],outd[N];
unsigned upper[N],space[N],space2[N],ans;
std::queue<int> q;
void kahn2() {
    for(register int i=1;i<=n;i++) {
        if(outd[i]==0) q.push(i);
    }
    while(!q.empty()) {
        const int &x=q.front();
        for(auto &j:e2[x]) {
            const int &y=j.to;
            const char &w=j.w;
            if(w=='_') space2[y]+=space2[x]+1;
            if(!--outd[y]) q.push(y);
        }
        q.pop();
    }
}
void kahn() {
    for(register int i=1;i<=n;i++) {
        if(ind[i]==0) q.push(i);
    }
    while(!q.empty()) {
        const int &x=q.front();
        for(auto &j:e[x]) {
            const int &y=j.to;
            const char &w=j.w;
            if(isupper(w)) upper[y]+=space[x]+1;
            if(islower(w)) upper[y]+=upper[x];
            if(w=='_') {
                space[y]+=space[x]+1;
                upper[y]+=upper[x];
            }
            if(w=='.') ans+=upper[x]*(space2[y]+1);
            if(!--ind[y]) q.push(y);
        }
        q.pop();
    }
}
int main() {
    n=getint(),m=getint();
    for(register int i=0;i<m;i++) {
        const int u=getint(),v=getint();
        const char w=getch();
        add_edge(u,v,w);
        add_edge2(v,u,w);
        ind[v]++;
        outd[u]++;
    }
    kahn2();
    kahn();
    printf("%u\n",ans);
    return 0;
}

D-整数序列

题目大意:

给出一个长度为\(n\)的整数序列\(a_1,a_2,\ldots,a_n\),进行\(m\)次操作,操作分为两类:

  1. 给出\(l,r,v\),将\(a_{l\sim r}\)分别加上\(v\);
  2. 给出\(l,r\),询问\(\sum_{i=l}^r\sin(a_i)\)。

思路:

根据三角恒等变换:
\[
\begin{align*}
\sin(\alpha+\beta)=\sin\alpha\cdot\cos\beta+\cos\alpha\cdot\sin\beta\\cos(\alpha+\beta)=\cos\alpha\cdot\cos\beta-\sin\alpha\cdot\sin\beta
\end{align*}
\]

用线段树维护区间\(\sum\sin(a_i)\)和区间\(\sum\cos(a_i)\)即可。

考虑写成复数的形式,\(\cos\)作为实部,\(\sin\)作为虚部。使用std::complex可以很方便的维护。

源代码:

#include<cmath>
#include<cstdio>
#include<cctype>
#include<complex>
#include<algorithm>
inline int getint() {
    register char ch;
    while(!isdigit(ch=getchar()));
    register int x=ch^'0';
    while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
    return x;
}
typedef long long int64;
typedef std::complex<double> comp;
const int N=2e5+1;
class SegmentTree {
    #define _left <<1
    #define _right <<1|1
    #define mid ((b+e)>>1)
    private:
        comp val[N<<2],tag[N<<2];
        void push_up(const int &p) {
            val[p]=val[p _left]+val[p _right];
        }
        void push_down(const int &p) {
            if(tag[p]==comp(1,0)) return;
            val[p _left]*=tag[p];
            val[p _right]*=tag[p];
            tag[p _left]*=tag[p];
            tag[p _right]*=tag[p];
            tag[p]=comp(1,0);
        }
    public:
        void build(const int &p,const int &b,const int &e) {
            if(b==e) {
                const int x=getint();
                val[p]=comp(cos(x),sin(x));
                return;
            }
            tag[p]=comp(1,0);
            build(p _left,b,mid);
            build(p _right,mid+1,e);
            push_up(p);
        }
        void modify(const int &p,const int &b,const int &e,const int &l,const int &r,const comp &x) {
            if(b==l&&e==r) {
                tag[p]*=x;
                val[p]*=x;
                return;
            }
            push_down(p);
            if(l<=mid) modify(p _left,b,mid,l,std::min(mid,r),x);
            if(r>mid) modify(p _right,mid+1,e,std::max(mid+1,l),r,x);
            push_up(p);
        }
        double query(const int &p,const int &b,const int &e,const int &l,const int &r) {
            if(b==l&&e==r) return val[p].imag();
            push_down(p);
            double ret=0;
            if(l<=mid) ret+=query(p _left,b,mid,l,std::min(mid,r));
            if(r>mid) ret+=query(p _right,mid+1,e,std::max(mid+1,l),r);
            return ret;
        }
    #undef _left
    #undef _right
    #undef mid
};
SegmentTree t;
int main() {
    const int n=getint();
    t.build(1,1,n);
    const int m=getint();
    for(register int i=0;i<m;i++) {
        const int opt=getint(),l=getint(),r=getint();
        if(opt==1) {
            const int x=getint();
            t.modify(1,1,n,l,r,comp(cos(x),sin(x)));
        }
        if(opt==2) {
            printf("%.1f\n",t.query(1,1,n,l,r));
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/skylee03/p/9495843.html

时间: 2024-10-10 00:06:33

Wannafly挑战赛22游记的相关文章

Wannafly挑战赛25游记

Wannafly挑战赛25游记 A - 因子 题目大意: 令\(x=n!(n\le10^{12})\),给定一大于\(1\)的正整数\(p(p\le10000)\)求一个\(k\)使得\(p^k|x\)并且\(p^{k+1}\not|x\)的因子. 思路: 枚举\(p\)的每一个质因数\(q\),求出它在\(n!\)出现次数\(/p\)中出现次数,取\(\min\)即可.对于一个质因数\(q\),在\(n!\)中出现的次数等于\(\sum_{i=1}^{\inf}\frac n{q^i}\).

Wannafly挑战赛22 A-计数器(gcd,裴蜀定理)

原题地址 题目描述 有一个计数器,计数器的初始值为0,每次操作你可以把计数器的值加上a1,a2,...,an中的任意一个整数,操作次数不限(可以为0次),问计数器的值对m取模后有几种可能. 输入描述: 第一行两个整数n,m接下来一行n个整数表示a1,a2,...,an1≤n≤1001≤m,a1,a2,...,an≤1000000000 输出描述: 输出一个整数表示答案 示例1 输入 复制 3 6 6 4 8 输出 复制 3 题解:假设K1为A1取的个数:根据题意题目变成a1*k1+a2*k2+a

Wannafly 挑战赛22 D 整数序列 线段树 区间更新,区间查询

题目链接:https://www.nowcoder.com/acm/contest/160/D 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 262144K,其他语言524288K 64bit IO Format: %lld 题目描述 给出一个长度为n的整数序列a1,a2,...,an,进行m次操作,操作分为两类. 操作1:给出l,r,v,将al,al+1,...,ar分别加上v: 操作2:给出l,r,询问 输入描述: n个数,m次操作op=1, l,r,v 区间[l,r] 加

Wannafly挑战赛3

Wannafly挑战赛3 A    珂朵莉 B    遇见 水题 #include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define rep(i,a,b) for (int i=a; i<=b; ++i) #define per(i,b,a) for (int i=b; i>=a; --i) #define mes(a

【Wannafly挑战赛4】F 线路规划 倍增+Kruskal+归并

[Wannafly挑战赛4]F 线路规划 题目描述 Q国的监察院是一个神秘的组织.这个组织掌握了整个帝国的地下力量,监察着Q国的每一个人.监察院一共有N个成员,每一个成员都有且仅有1个直接上司,而他只听从其上直接司的命令.其中1号成员是监察院的院长,这个庞然大物的主人.由于时代的进步,监察院议会决定升级组织的旧式通信器,安装最新的反侦测通信器.他们拿出了M组线路方案,其中第i组线路方案可以用一个四元组(x[i].y[i].k[i].w[i])描述,表示第x[i]号成员可以安装与y[i]号成员的直

牛客网 Wannafly挑战赛8 C-小C打比赛 (状压DP)

小C现在要参加一场wannafly挑战赛,一场挑战赛一共有n道题,一共有m分钟. 对于第i道题,小C解决它需要恰好j分钟的概率是pi,j. 小C每次会选择某一道没做完的题,然后把它解决(不能中途放弃),之后再决策下一道要做的题是哪道. 求小C在最优策略下,期望能做出几道题. 输入描述: 第一行两个正整数n,m接下来一共n行,每行有m个小数,第i行的第j个小数表示p i,j (这里假设不存在0分钟A题的dalao). 输出描述: 输出一个小数,表示期望能做出几道题,保留小数点后五位. 示例1 输入

Wannafly挑战赛11 D 白兔的字符串 Hash

Wannafly挑战赛11 D   白兔的字符串 白兔有一个字符串T.白云有若干个字符串S1,S2..Sn. 白兔想知道,对于白云的每一个字符串,它有多少个子串是和T循环同构的. 提示:对于一个字符串a,每次把a的第一个字符移动到最后一个,如果操作若干次后能够得到字符串b,则a和b循环同构. 所有字符都是小写英文字母 输入描述: 第一行一个字符串T(|T|<=10^6)第二行一个正整数n (n<=1000)接下来n行为S1~Sn (|S1|+|S2|+…+|Sn|<=10^7),max(

Wannafly挑战赛18

Wannafly挑战赛18 A. 序列 先考虑暴力,相邻两个树之间乘上给定的三种数,递推出下一个位置填什么,然后再check一下,最后一位是否为1即可.这样时间显然不行,但是给我们一种思路,就是中间的转换关系,确定唯一一个序列.现在的目标是让最后一位出现1,可以如果不管1,由-2和0.5取凑出1需要两个-2和两个0.5.那所有的转换中,就只要保证有若干组(-2,-2,0.5,0.5)存在,其他地方为1即可.具体公式见代码 #include <bits/stdc++.h> #define rep

Wannafly挑战赛19

Wannafly挑战赛19 A. 队列Q 需要支持把一个元素移到队首,把一个元素移到队尾,移到队首就直接放到队首前面那个位置,原位置标为0,队尾同理. #include <bits/stdc++.h> #define rep(i,a,b) for(int i=a;i<=b;++i) typedef long long ll; const int N = 30000200; using namespace std; int n,m; int q[N],hd,x,ed,P[N]; char