「雅礼集训 2017 Day8」价~「2017 山东一轮集训 Day1」Set

1981: #6045. 「雅礼集训 2017 Day8」价

题目描述

人类智慧之神 zhangzj 最近有点胖,所以要减肥,他买了 N NN 种减肥药,发现每种减肥药使用了若干种药材,总共正好有 N NN 种不同的药材。

经过他的人脑实验,他发现如果他吃下去了 K KK(0≤K≤N 0 \leq K \leq N0≤K≤N)种减肥药,而这 K KK 种减肥药使用的药材并集大小也为 K KK,这 K KK 种才会有效果,否则无效。
第 i ii 种减肥药在产生效果的时候会使 zhangzj 的体重增加 Pi P_iPi 斤,显然 Pi P_iPi 可以小于 0 00。

他想知道,一次吃药最好情况下体重变化量是多少,当然可以一种药也不吃,此时体重不变。 由于某些奥妙重重的情况,我们可以让这 N NN 种减肥药每一种对应一个其使用的药材,且 N NN 种减肥药对应的药材互不相同(即有完美匹配)。

输入

第一行一个整数 N NN。

接下来 N NN 行,每行描述一种减肥药,对于一种减肥药,第一个数读入使用的药材个数 t tt,接下来 t tt 个整数表示使用的药材编号,一个药材编号在一行只会出现一次。
最后一行 N NN 个整数,第 i ii 个整数 Pi P_iPi 表示第 i ii 种减肥药产生效果时的体重变化量。

输出

一行一个整数表示答案。

样例输入 

3
2 1 2
2 1 2
1 3
-10 20 -3

样例输出 

-3

提示

对于 30% 30\%30% 的数据,N≤20 N \leq 20N≤20;
对于另外 10% 10\%10% 的数据,Pi<0 P_i < 0Pi<0;
对于 100% 100\%100% 的数据,1≤N≤300,∣Pi∣≤1000000 1 \leq N \leq 300, |P_i| \leq 10000001≤N≤300,∣Pi∣≤1000000。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <queue>
#define UP 2000000
#define inf 0x7fffffff
#define N 666
using namespace std;
int e=2,head[N];
struct edge{
    int u,v,f,next;
}ed[N*N];
void add(int u,int v,int f){
    ed[e].u=u;ed[e].v=v;ed[e].f=f;
    ed[e].next=head[u];head[u]=e++;
    ed[e].u=v;ed[e].v=u;ed[e].f=0;
    ed[e].next=head[v];head[v]=e++;
}
int n,ans,S,T,dep[N];
bool bfs(){
    memset(dep,0,sizeof dep);
    queue<int> q;q.push(S);dep[S]=1;
    while(!q.empty()){
        int x=q.front();q.pop();
        for(int i=head[x];i;i=ed[i].next){
            if(ed[i].f&&!dep[ed[i].v]){
                dep[ed[i].v]=dep[x]+1;
                if(ed[i].v==T)return 1;
                q.push(ed[i].v);
            }
        }
    }
    return 0;
}
int dfs(int x,int f){
    if(x==T||!f)return f;
    int ans=0;
    for(int i=head[x];i;i=ed[i].next){
        if(ed[i].f&&dep[ed[i].v]==dep[x]+1){
            int nxt=dfs(ed[i].v,min(f,ed[i].f));
            ans+=nxt,f-=nxt;ed[i].f-=nxt,ed[i^1].f+=nxt;
            if(!f)break;
        }
    }
    if(!ans)dep[x]=-1;
    return ans;
}
int dinic(){
    int ans=0;
    while(bfs())ans+=dfs(S,inf);
    return ans;
}
int main(){
    // freopen("test.in","r",stdin);
    scanf("%d",&n);
    S=2*n+1;T=S+1;
    for(int i=1,j,k;i<=n;i++){
        scanf("%d",&j);
        while(j--){
            scanf("%d",&k);
            add(i,n+k,inf);
        }
    }
    for(int i=1,x;i<=n;i++){
        scanf("%d",&x);
        add(S,i,UP-x);
        add(n+i,T,UP);
        ans-=UP-x;
    }
    ans+=dinic();
    printf("%d\n",ans);
}

1982: #6046. 「雅礼集训 2017 Day8」爷

题目描述

如果你对山口丁和 G&P 没有兴趣,可以无视题目背景,因为你估计看不懂 ……

在第 63 回战车道全国高中生大赛中,军神西住美穗带领大洗女子学院的大家打败了其他所有高中,取得了胜利,当然也就不用废校了。
然而一群战车道的领导表示他们是口胡的,废校还是要废的。

军神的母亲西住志穗怒斥废校男,为了不造个大新闻,废校男承诺如果大洗学院可以打败大学队,就不用废校。
(有种 OI 选手 PK ACM 选手的感觉呀)
然而实力差距太大了,大洗女子学院最强的车是虎式 P 型,而大学队清一色的 M26 潘兴,M24 霞飞(突然发现现在霞飞被砍的好惨),还有能跑到 20 的 T95 和卡尔臼炮,感觉根本没法打呀。
这时候一个光头的胖子谢尔盖 • 布尔卡托夫斯基和一个身患癌症急需钱来治病的王姓 CEO 来帮助她们了。
他们把一堆真实性堪忧的坦克图纸给了大洗学院的妹子们,并说这些图纸是真的,而且还原了历史。
大洗学院汽车部的大家看到了这些图纸后非常高兴,开始膜改她们的战车。
虎式 P 型 -> 蟋蟀 17
四号 D 型 -> 四号坦克武器运载车
38(t) 型 -> 莱茵金属公司武器运载车
B1-bis -> 105leFH18B2
即使这样,只有 8 辆战车的大洗女子学院仍然无法打败有 30 辆战车的大学队。

这时候按照剧本其他高中的小伙伴要来帮忙了,然而她们最近正在学习 OI,碰到了一道很神奇的数据结构题,不会做所以来不了。 你作为一个三次元的国家队选手,当然能秒杀二次元的 OI 题啦。 请帮帮她们吧!

给你一个 n nn 个点的有根树,1 11 为根,带边权,有 m mm 次操作。

  1. 求 x xx 的子树中第 k kk 小的深度的值,如果子树中没有 k kk 个点则输出 −1 -1−1;
  2. 江 x xx 与 x xx 父亲的边权加上 k kk。

保证每次操作 2 的 k kk 以及原树的边权小于等于一个数 len \text{len}len。

如果操作 2 中 x xx 为 1 11,那么视为将 x xx 的基础深度加上了 k kk。

输入

第一行三个数 n nn、m mm、len \text{len}len。
之后 n−1 n - 1n−1 行每行两个数表示 2∼n 2 \sim n2∼n 每个点的父亲编号,以及他们到父亲的边权。
之后 m mm 行每行三个数 opt \text{opt}opt、x xx、k kk,opt \text{opt}opt 表示操作种类,x xx、k kk 意义如题所述。

输出

对于每个操作 1,输出一个数表示答案。

样例输入 

3 5 3
1 3
2 3
1 1 3
2 3 3
1 1 3
2 1 2
1 1 3

样例输出 

6
9
11

提示

对于 10% 10\%10% 的数据,n,m≤1000 n, m \leq 1000n,m≤1000;
对于 30% 30\%30% 的数据,n,m≤30000 n, m \leq 30000n,m≤30000;
对于 100% 100\%100% 的数据,n,m≤100000,len≤10 n, m \leq 100000, \text{len} \leq 10n,m≤100000,len≤10。

本水题采用捆绑测试,你只有通过该部分分的所有数据才可以得到该部分分的分数。

如果你对山口丁和 G&P 没有兴趣,可以无视结局。
如果你做出来了这个题
妹子们看了你的 STD 之后都 A 了这个题,然后去帮助军神。
她们找了 30 个 183 射了对面一脸。
如果你没做出来这个题
妹子们虽然很想帮助军神,但是也爱莫能助,毕竟学战车道不能保送。
没有办法,只能 8 打 30 了。
莱茵蹲在草里,大学队没有人发现它,成功击杀五辆敌方坦克后因为车体无法承受火炮后坐力而解体。
三突也蹲在草里,大学队没有人发现它,它也没有发现任何人,最后蹲不住了去突击,击毁一辆潘兴后被击毁。
四运文艺倒车,大学队看到之后目瞪口呆,成功击杀八辆敌方坦克后因为车体无法承受火炮后坐力而解体。
虎 P 炮一发带走了 95,然后因为转场的时候发动机故障而烧毁。
最后法五金刺刀了 15 个,成功翻盘。

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<ctime>
#include<set>
using namespace std;
#define ll long long
#define db double
#define For(i,a,b) for(register int i=(a);i<=(b);++i)
#define Rep(i,a,b) for(register int i=(a);i>=(b);--i)
const int maxn=2e5+7,maxt=1000+7,maxs=2e4+7,S=2e3,INF=0x3f3f3f3f;
int n,m,len,a[maxn],bel[maxn],sz;
int L[maxn],R[maxn];
  
char cc;ll ff;
template<typename T>void read(T& aa) {
    aa=0;cc=getchar();ff=1;
    while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
    if(cc=='-') ff=-1,cc=getchar();
    while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    aa*=ff;
}
  
int fir[maxn],nxt[maxn],to[maxn],e=0,v[maxn];
void add(int x,int y,int z) {
    to[++e]=y;nxt[e]=fir[x];fir[x]=e;v[e]=z;
}
  
int dfn[maxn],fed[maxn],dfn_clock;
void dfs(int pos,int d) {
    dfn[pos]=++dfn_clock;
    a[dfn_clock]=d;
    for(int y=fir[pos];y;y=nxt[y]) dfs(to[y],d+v[y]);
    fed[pos]=dfn_clock;
}
  
int sum[maxt][maxs],pl[maxt],pr[maxt],tot;
int d[maxn];
  
inline void pd(int x) {
    if(!d[x]) return;
    For(i,L[x],R[x]) a[i]+=d[x];
    d[x]=0;
}
  
inline void ud(int x) {
    pl[x]=INF; pr[x]=-INF;
    For(j,L[x],R[x]) {
        pl[x]=min(pl[x],a[j]);
        pr[x]=max(pr[x],a[j]);
    }
    For(j,0,pr[x]-pl[x]) sum[x][j]=0;
    For(j,L[x],R[x]) ++sum[x][a[j]-pl[x]];
    For(j,1,pr[x]-pl[x]) sum[x][j]+=sum[x][j-1];
}
  
void bld() {
    For(i,1,tot) pd(i);
    int now=1,ld=INF,rd=-INF; L[1]=1;
    For(i,1,n) {
        ld=min(ld,a[i]); rd=max(rd,a[i]);
        if(rd-ld>S||i-L[now]>=sz) {
            R[now]=i-1;
            L[++now]=i;
            ld=rd=a[i];
        }
        R[bel[i]=now]=i;
    }
    tot=now;
    For(i,1,tot) ud(i);
}
  
inline int get_sum(int p,int x) {
    if(x<pl[p]) return 0;
    if(x>pr[p]) return sum[p][pr[p]-pl[p]];
    return sum[p][x-pl[p]];
}
  
inline int q(int ld,int rd,int x) {
    int rs=0,lt=bel[ld],rt=bel[rd];
    if(lt==rt) {
        For(i,ld,rd) if(a[i]<=x) ++rs;
        return rs;
    }
    if(ld!=L[lt]) {For(i,ld,R[lt]) if(a[i]<=x) ++rs;}
    else rs+=get_sum(lt,x);
    if(rd!=R[rt]) {For(i,L[rt],rd) if(a[i]<=x) ++rs;}
    else rs+=get_sum(rt,x);
    For(i,lt+1,rt-1) rs+=get_sum(i,x);
    return rs;
}
  
inline int Yth(int ld,int rd,int k) {
    int lt=bel[ld],rt=bel[rd];
    pd(lt); pd(rt);
    if(rd-ld+1<k) return -1;
    int l=INF,r=-INF,mid;
    For(i,lt,rt) l=min(l,pl[i]),r=max(r,pr[i]);
    if(l==r) return l; --l;
    while(l<r-1) {
        mid=(l+r)>>1;
        if(q(ld,rd,mid)>=k) r=mid;
        else l=mid;
    }
    return r;
}
  
inline void chge(int ld,int rd,int x) {
    int lt=bel[ld],rt=bel[rd];
    if(lt==rt) {
        pd(lt); For(i,ld,rd) a[i]+=x; ud(lt);
        return;
    }
    if(ld!=L[lt]) {
        pd(lt); For(i,ld,R[lt]) a[i]+=x; ud(lt);
    }
    else d[lt]+=x,pl[lt]+=x,pr[lt]+=x;
    if(rd!=R[rt]) {
        pd(rt); For(i,L[rt],rd) a[i]+=x; ud(rt);
    }
    else d[rt]+=x,pl[rt]+=x,pr[rt]+=x;
    For(i,lt+1,rt-1) d[i]+=x,pl[i]+=x,pr[i]+=x;
}
  
int main() {
    read(n); read(m); read(len); sz=300;
    int op,x,y;
    For(i,2,n) {
        read(x); read(y);
        add(x,i,y);
    }
    dfs(1,0);
    bld();
    For(i,1,m) {
        read(op); read(x); read(y);
        if(op==1) printf("%d\n",Yth(dfn[x],fed[x],y));
        else chge(dfn[x],fed[x],y);
        if(i%1000==0) bld();
    }
    return 0;
}

1983: #6050. 「雅礼集训 2017 Day11」TRI

题目描述

给定 n nn 和 m mm,求出所有顶点坐标满足0≤x0≤x<n,0≤y<m 的格点三角形的面积和的两倍。答案模 1004535809 10045358091004535809 输出。

输入

一行两个整数 n nn 和 m mm。

输出

一行一个整数表示答案。

样例输入 

2 3

样例输出 

24

提示

测试点n nnm mm
1≤10 \leq 10≤10≤10 \leq 10≤10
2≤20 \leq 20≤20≤20 \leq 20≤20
3≤30 \leq 30≤30≤30 \leq 30≤30
4≤40 \leq 40≤40≤40 \leq 40≤40
5≤50 \leq 50≤50≤50 \leq 50≤50
6≤60 \leq 60≤60≤60 \leq 60≤60
7≤100 \leq 100≤100≤100 \leq 100≤100
8≤200 \leq 200≤200≤200 \leq 200≤200
9≤300 \leq 300≤300≤300 \leq 300≤300
10≤400 \leq 400≤400≤400 \leq 400≤400
11≤1000 \leq 1000≤1000≤1000 \leq 1000≤1000
12≤2000 \leq 2000≤2000≤2000 \leq 2000≤2000
13≤2500 \leq 2500≤2500≤2500 \leq 2500≤2500
14≤3000 \leq 3000≤3000≤3000 \leq 3000≤3000
15≤1000 \leq 1000≤1000≤109 \leq 10 ^ 9≤109
16≤1500 \leq 1500≤1500≤109 \leq 10 ^ 9≤109
17≤2000 \leq 2000≤2000≤109 \leq 10 ^ 9≤109
18≤2500 \leq 2500≤2500≤109 \leq 10 ^ 9≤109
19≤2800 \leq 2800≤2800≤109 \leq 10 ^ 9≤109
20≤3000 \leq 3000≤3000≤109 \leq 10 ^ 9≤109

#include<cstdio>
#define RI register int
#define CI const int&
using namespace std;
const int N=3005,mod=1004535809;
int n,m,mu[N],ans;
inline void swap(int& x,int& y)
{
	int t=x; x=y; y=t;
}
inline int sum(CI x,CI y)
{
	int t=x+y; return t>=mod?t-mod:t;
}
inline void dec(int& x,CI y)
{
	if ((x-=y)<0) x+=mod;
}
inline int inv(int x,int p=mod-2,int mul=1)
{
	for (;p;p>>=1,x=1LL*x*x%mod) if (p&1) mul=1LL*mul*x%mod; return mul;
}
int main()
{
	RI i,j; scanf("%d%d",&n,&m); if (n>m) swap(n,m);
	for (i=1;i<=n;++i) mu[i]=i*i; for (i=1;i<=n;++i)
	for (j=i<<1;j<=n;j+=i) mu[j]-=mu[i];
	ans=1LL*n*(n-1)%mod*m%mod*(m-1)%mod*sum(11LL*n*(n+1)%mod*m%mod*(m+1)%mod,
	6LL*sum(1LL*n*(n+1)%mod,1LL*m*(m+1)%mod)%mod)%mod*inv(144)%mod;
	for (i=1;i<=n;++i) dec(ans,1LL*mu[i]*(n-i+n%i)%mod*(n/i)%mod*
	inv(2)%mod*(m-i+m%i)%mod*(m/i)%mod*inv(2)%mod);
	return printf("%d",1LL*ans*inv(3)%mod),0;
}

1984: #6051. 「雅礼集训 2017 Day11」PATH

题目描述

给定 n nn 和 {ai} \{a_i\}{ai},满足 a0≥a1≥⋯≥an−1≥0 a_0 \geq a_1 \geq \cdots \geq a_{n - 1} \geq 0a0≥a1≥⋯≥an−1≥0,求出在 n nn 维空间中从 (0,0,…,0) (0, 0, \ldots, 0)(0,0,…,0) 走到 (a0,a1,…,an−1) (a_0, a_1, \ldots, a_{n - 1})(a0,a1,…,an−1),每一步使某一维坐标增加 1 11 的方案中随机选出一种,满足经过的所有点 (x0,x1,…,xn−1) (x_0, x_1, \ldots, x_{n - 1})(x0,x1,…,xn−1) 都满足 x0≥x1≥⋯≥xn−1 x_0 \geq x_1 \geq \cdots \geq x_{n - 1}x0≥x1≥⋯≥xn−1 的概率,答案模 1004535809 10045358091004535809 输出。

输入

第一行一个整数 n nn,接下来一行 n nn 个整数表示 ai a_iai。

输出

一行一个整数表示答案。

样例输入 

2
3 3

样例输出 

753401857

提示

测试点n nnai a_iai特殊限制
14 44≤4 \leq 4≤4
26 66≤6 \leq 6≤6
38 88≤8 \leq 8≤8
410 1010≤10 \leq 10≤10
52 22≤500000 \leq 500000≤500000所有 ai a_iai 相等
62 22≤500000 \leq 500000≤500000
73 33≤500000 \leq 500000≤500000所有 ai a_iai 相等
83 33≤500000 \leq 500000≤500000
93000 30003000≤500000 \leq 500000≤500000所有 ai a_iai 相等
103000 30003000≤500000 \leq 500000≤500000
11500000 500000500000≤500000 \leq 500000≤500000所有 ai a_iai 相等
12500000 500000500000≤500000 \leq 500000≤500000ai a_iai 为等差数列
13500000 500000500000≤50 \leq 50≤50
14500000 500000500000≤3000 \leq 3000≤3000
1530000 3000030000≤30000 \leq 30000≤30000
1650000 5000050000≤50000 \leq 50000≤50000
17100000 100000100000≤100000 \leq 100000≤100000
18200000 200000200000≤200000 \leq 200000≤200000
19300000 300000300000≤300000 \leq 300000≤300000
20500000 500000500000≤500000 \leq 500000≤500000

#include<cstdio>
#include<cctype>
#define RI register int
#define CI const int&
#define Tp template <typename T>
using namespace std;
const int N=500005,mod=1004535809;
int n,m,len,lim,a[N],b[N],fact[N],F[N<<3],G[N<<3],ans;
class FileInputOutput
{
    private:
        static const int S=1<<21;
        #define tc() (A==B&&(B=(A=Fin)+fread(Fin,1,S,stdin),A==B)?EOF:*A++)
        char Fin[S],*A,*B;
    public:
        Tp inline void read(T& x)
        {
            x=0; char ch; while (!isdigit(ch=tc()));
            while (x=(x<<3)+(x<<1)+(ch&15),isdigit(ch=tc()));
        }
        #undef tc
}File;
inline void maxer(int& x,CI y)
{
    if (y>x) x=y;
}
inline int quick_pow(int x,int p=mod-2,int mul=1)
{
    for (;p;p>>=1,x=1LL*x*x%mod) if (p&1) mul=1LL*mul*x%mod; return mul;
}
class Poly_solver
{
    private:
        int rev[N<<3],p;
        inline void swap(int& x,int& y)
        {
            int t=x; x=y; y=t;
        }
        inline int sum(CI a,CI b)
        {
            int t=a+b; return t>=mod?t-mod:t;
        }
        inline int sub(CI a,CI b)
        {
            int t=a-b; return t<0?t+mod:t;
        }
    public:
        inline void init(CI n)
        {
            for (lim=1,p=0;lim<=n;lim<<=1,++p);
            for (RI i=0;i<lim;++i) rev[i]=(rev[i>>1]>>1)|((i&1)<<p-1);
        }
        inline void NTT(int *f,CI opt)
        {
            RI i; for (i=0;i<lim;++i) if (i<rev[i]) swap(f[i],f[rev[i]]);
            for (i=1;i<lim;i<<=1)
            {
                int m=i<<1,D=quick_pow(3,~opt?(mod-1)/m:mod-1-(mod-1)/m);
                for (RI j=0;j<lim;j+=m)
                {
                    int W=1; for (RI k=0;k<i;++k,W=1LL*W*D%mod)
                    {
                        int x=f[j+k],y=1LL*f[i+j+k]*W%mod;
                        f[j+k]=sum(x,y); f[i+j+k]=sub(x,y);
                    }
                }
            }
            if (!~opt)
            {
                int Inv=quick_pow(lim); for (i=0;i<lim;++i) f[i]=1LL*f[i]*Inv%mod;
            }
        }
}P;
int main()
{
    //freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
    RI i; for (File.read(n),i=1;i<=n;++i)
    File.read(a[i]),b[a[i]]=i,++F[a[i]-i+n];
    for (i=m=a[1];i;--i) maxer(b[i],b[i+1]),++G[b[i]-i+m];
    for (P.init((len=n+m)<<1),P.NTT(F,1),P.NTT(G,1),i=0;i<lim;++i)
    F[i]=1LL*F[i]*G[i]%mod; for (P.NTT(F,-1),i=ans=1;i<=len;++i)
    ans=1LL*ans*quick_pow(i,F[i-1+n+m])%mod; ans=quick_pow(ans);
    for (fact[0]=i=1;i<=m;++i) fact[i]=1LL*fact[i-1]*i%mod;
    for (i=1;i<=n;++i) ans=1LL*ans*fact[a[i]]%mod;
    return printf("%d",ans),0;
}

1985: #6052. 「雅礼集训 2017 Day11」DIV

题目描述

定义复数 a+bi a + bia+bi 为整数 k kk 的约数,当且仅当 a aa 和 b bb 为整数且存在整数 c cc 和 d dd 满足 (a+bi)(c+di)=k (a + bi)(c + di) = k(a+bi)(c+di)=k,给定 n nn,求出 1 11 到 n nn 的所有满足 a>0 a > 0a>0 的约数 a+bi a + bia+bi 的 a aa 的和。答案模 1004535809 10045358091004535809 输出。

输入

一行一个整数 n nn。

输出

一行一个整数表示答案。

样例输入 

5

样例输出 

35

提示

测试点n nn
1≤10 \leq 10≤10
2≤100 \leq 100≤100
3≤200 \leq 200≤200
4≤300 \leq 300≤300
5≤400 \leq 400≤400
6≤500 \leq 500≤500
7≤3000 \leq 3000≤3000
8≤5000 \leq 5000≤5000
9≤3×106 \leq 3 \times 10 ^ 6≤3×106
10≤5×106 \leq 5 \times 10 ^ 6≤5×106
11≤7×106 \leq 7 \times 10 ^ 6≤7×106
12≤107 \leq 10 ^ 7≤107
13≤3×108 \leq 3 \times 10 ^ 8≤3×108
14≤5×108 \leq 5 \times 10 ^ 8≤5×108
15≤7×108 \leq 7 \times 10 ^ 8≤7×108
16≤109 \leq 10 ^ 9≤109
17≤3×109 \leq 3 \times 10 ^ 9≤3×109
18≤5×109 \leq 5 \times 10 ^ 9≤5×109
19≤7×109 \leq 7 \times 10 ^ 9≤7×109
20≤1010 \leq 10 ^ {10}≤1010

#include<cstdio>
#include<map>
#include<cmath>
#define RI register int
#define CI const int&
using namespace std;
typedef long long LL;
const int N=5000000,mod=1004535809,inv2=502267905;
int prime[N+5],cnt,ans; bool vis[N+5];
LL n,ds[N+5],fs[N+5]; map <LL,int> _ds,_fs;
inline void inc(LL& x,const LL y)
{if ((x+=y)>=mod) x-=mod;
}
inline void inc(int& x,CI y)
{if ((x+=y)>=mod) x-=mod;
}
inline void dec(int& x,CI y)
{if ((x-=y)<0) x+=mod;
}
inline int sum(CI x,CI y)
{int t=x+y; return t>=mod?t-mod:t;
}
inline int sub(CI x,CI y)
{int t=x-y; return t<0?t+mod:t;
}
inline int gcd(CI x,CI y)
{return y?gcd(y,x%y):x;
}
inline int Sum(const LL& l,const LL& r)
{return ((l+r)%mod)*((r-l+1)%mod)%mod*inv2%mod;
}
#define Pi prime[j]
inline void init(CI n)
{RI i,j; ds[1]=vis[1]=1; for (i=2;i<=n;++i){if (!vis[i]) prime[++cnt]=i,ds[i]=i+1;for (j=1;j<=cnt&&i*Pi<=n;++j){vis[i*Pi]=1; if (i%Pi) ds[i*Pi]=ds[i]*(Pi+1);else { ds[i*Pi]=ds[i]*(Pi+1)-Pi*ds[i/Pi]; break; }}}for (i=1;i*i<=n;++i){int t=i*i; for (j=1;j*j+t<=n;++j) if (gcd(i,j)==1) fs[j*j+t]+=i;}for (i=1;i<=n;++i) ds[i]%=mod,fs[i]%=mod,inc(ds[i],ds[i-1]),inc(fs[i],fs[i-1]);
}
#undef Pi
inline int Ds(const LL& x)
{if (x<=N) return ds[x]; if (_ds.count(x)) return _ds[x]; int ret=0;for (LL l=1,r;l<=x;l=r+1) r=x/(x/l),inc(ret,1LL*Sum(l,r)*((x/r)%mod)%mod); return _ds[x]=ret;
}
inline int Fs(const LL& x)
{if (x<=N) return fs[x]; if (_fs.count(x)) return _fs[x]; int ret=0; register LL i; for (i=1;i*i<=x;++i) inc(ret,i*((LL)floor(sqrt(x-i*i))%mod)%mod);for (i=2;i*i<=x;++i) dec(ret,i*Fs(x/(i*i))%mod); return _fs[x]=ret;
}
int main()
{scanf("%lld",&n); init(N); for (LL l=1,r;l<=n;l=r+1)r=n/(n/l),inc(ans,1LL*sub(Fs(r),Fs(l-1))*Ds(n/l)%mod);return printf("%d",sum(sum(ans,ans),Ds(n))),0;
}

1986: #6059. 「2017 山东一轮集训 Day1」Sum

题目描述

求有多少 n nn 位十进制数是 p pp 的倍数且每位之和小于等于 mi(mi=0,1,2,…,m−1,m) m_i (m_i = 0, 1, 2, \ldots, m - 1, m)mi(mi=0,1,2,…,m−1,m),允许前导 0 00,答案对 998244353 998244353998244353 取模。

输入

一行三个整数 n,p,m n, p, mn,p,m。

输出

输出一行 m+1 m + 1m+1 个正整数,分别表示 mi=0,1,2,…,m−1,m m_i = 0, 1, 2, \ldots, m - 1, mmi=0,1,2,…,m−1,m 时的答案。

样例输入 

2 3 3

样例输出 

1 1 1 5

提示

对于测试点 1,1≤n≤1000,1≤p≤50.1≤m≤5 1 \leq n \leq 1000, 1 \leq p \leq 50.1 \leq m \leq 51≤n≤1000,1≤p≤50.1≤m≤5;
对于测试点 2、3,1≤n≤109,1≤p≤50.1≤m≤5 1 \leq n \leq 10^9, 1 \leq p \leq 50.1 \leq m \leq 51≤n≤109,1≤p≤50.1≤m≤5;
对于测试点 4、5、6,1≤n≤109,1≤p≤50.1≤m≤50 1 \leq n \leq 10^9, 1 \leq p \leq 50.1 \leq m \leq 501≤n≤109,1≤p≤50.1≤m≤50;
对于测试点 7、8、9、10,1≤n≤109,1≤p≤16.1≤m≤1000 1 \leq n \leq 10^9, 1 \leq p \leq 16.1 \leq m \leq 10001≤n≤109,1≤p≤16.1≤m≤1000。

#include<cstdio>
#include<iostream>
#define RI register int
#define CI const int&
using namespace std;
const int N=1005,mod=998244353;
int n,p,m,f[50][N],g[50][N],p10,ans;
inline int quick_pow(int x,int p=mod-2,int mul=1)
{
    for (;p;p>>=1,x=1LL*x*x%mod) if (p&1) mul=1LL*mul*x%mod; return mul;
}
namespace Poly
{
    int rev[N<<2],A[N<<2],B[N<<2],lim,p;
    inline void NTT(int* f,CI opt)
    {
        RI i,j,k; for (i=0;i<lim;++i) if (i<rev[i]) swap(f[i],f[rev[i]]);
        for (i=1;i<lim;i<<=1)
        {
            int D=quick_pow(3,opt==1?(mod-1)/(i<<1):mod-1-(mod-1)/(i<<1)),W;
            for (j=0;j<lim;j+=(i<<1)) for (W=1,k=0;k<i;++k,W=1LL*W*D%mod)
            {
                int x=f[j+k],y=1LL*f[i+j+k]*W%mod;
                f[j+k]=(x+y)%mod; f[i+j+k]=(x-y+mod)%mod;
            }   
        }
        if (!~opt)
        {
            int Inv=quick_pow(lim); for (i=0;i<lim;++i) f[i]=1LL*f[i]*Inv%mod;
        }
    }
    inline void init(CI n)
    {
        for (lim=1,p=0;lim<=(m<<1);lim<<=1,++p);
        for (RI i=0;i<lim;++i) rev[i]=(rev[i>>1]>>1)|((i&1)<<p-1);
    }
    inline void Convolution(int* a,int* b,int* c)
    {
        RI i; for (i=0;i<lim;++i) A[i]=B[i]=0;
        for (i=0;i<=m;++i) A[i]=a[i],B[i]=b[i];
        for (NTT(A,1),NTT(B,1),i=0;i<lim;++i) A[i]=1LL*A[i]*B[i]%mod;
        for (NTT(A,-1),i=0;i<=m;++i) (c[i]+=A[i])%=mod; 
    }
};
inline void solve(CI n)
{
    if (!n) return (void)(f[0][0]=p10=1); solve(n>>1);
    RI i,j,k; for (i=0;i<p;++i) for (j=0;j<=m;++j) g[i][j]=0;
    for (i=0;i<p;++i) for (j=0;j<p;++j) Poly::Convolution(f[i],f[j],g[(i*p10+j)%p]);
    for (i=0;i<p;++i) for (j=0;j<=m;++j) f[i][j]=g[i][j];
    if (n&1)
    {
        for (i=0;i<p;++i) for (j=0;j<=m;++j) g[i][j]=0;
        for (i=0;i<p;++i) for (j=0;j<=m;++j)
        for (k=0;k<=9&&j+k<=m;++k) (g[(i*10+k)%p][j+k]+=f[i][j])%=mod;
        for (i=0;i<p;++i) for (j=0;j<=m;++j) f[i][j]=g[i][j];
    }
    p10=p10*p10%p; if (n&1) (p10*=10)%=p;
}
int main()
{
    scanf("%d%d%d",&n,&p,&m); Poly::init(m); solve(n);
    for (RI i=0;i<=m;++i) (ans+=f[0][i])%=mod,printf("%d ",ans);
    return 0;
}

1987: #6060. 「2017 山东一轮集训 Day1」Set

题目描述

给出 n nn 个非负整数,将数划分成两个集合,记为一号集合和二号集合。x1 x_1x1 为一号集合中所有数的异或和,x2 x_2x2 为二号集合中所有数的异或和。在最大化 x1+x2 x_1 + x_2x1+x2 的前提下,最小化 x1 x_1x1。

输入

第一行包含一个整数 n nn。
第二行包含 n nn 个用空格隔开的数字,保证它们都是不超过 1018 10 ^ {18}1018 的非负整数。

输出

输出一行一个数,表示最优方案中的 x1 x_1x1。

样例输入 

8
1 1 2 2 3 3 4 4

样例输出 

7

提示

对于 30% 30\%30% 的数据,n≤10 n \leq 10n≤10;
对于 60% 60\%60% 的数据,n≤1000 n \leq 1000n≤1000;
对于 100% 100\%100% 的数据,n≤100000 n \leq 100000n≤100000。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=67;
ll ci[maxn],a[maxn],n;
ll Xor,now,num[100005];
  
inline void ins(ll x){
    for(int i=60;i>=0;i--)  if(!(Xor&ci[i])) if(x&ci[i]){
        if(!a[i]){ a[i]=x; return;}
        x^=a[i];
    }
      
    for(int i=60;i>=0;i--)  if(Xor&ci[i]) if(x&ci[i]){
        if(!a[i]){ a[i]=x; return;}
        x^=a[i];
    }  
}
  
inline ll read(){
    ll x=0; char ch=getchar();
    for(;!isdigit(ch);ch=getchar());
    for(;isdigit(ch);ch=getchar()) x=x*10ll+ch-'0';
    return x;
}
  
inline void solve(){   
    now=0;
      
    for(int i=60;i>=0;i--) if(!(Xor&ci[i])&&!(now&ci[i])) now^=a[i];
      
    for(int i=60;i>=0;i--) if((Xor&ci[i])&&!(now&ci[i])) now^=a[i];
}
  
int main(){
//  freopen("data.in","r",stdin);
//  freopen("data.out","w",stdout);
      
    ci[0]=1;
    for(int i=1;i<=60;i++) ci[i]=ci[i-1]+ci[i-1];
      
    scanf("%d",&n);
    for(int i=1;i<=n;i++) num[i]=read(),Xor^=num[i];
      
    for(int i=1;i<=n;i++) ins(num[i]);
      
    solve();
      
    printf("%lld\n",Xor^now);
  
    return 0;
}

  • 32
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值