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 次操作。
- 求 x xx 的子树中第 k kk 小的深度的值,如果子树中没有 k kk 个点则输出 −1 -1−1;
- 江 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 nn | m 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 nn | ai a_iai | 特殊限制 |
---|---|---|---|
1 | 4 44 | ≤4 \leq 4≤4 | |
2 | 6 66 | ≤6 \leq 6≤6 | |
3 | 8 88 | ≤8 \leq 8≤8 | |
4 | 10 1010 | ≤10 \leq 10≤10 | |
5 | 2 22 | ≤500000 \leq 500000≤500000 | 所有 ai a_iai 相等 |
6 | 2 22 | ≤500000 \leq 500000≤500000 | |
7 | 3 33 | ≤500000 \leq 500000≤500000 | 所有 ai a_iai 相等 |
8 | 3 33 | ≤500000 \leq 500000≤500000 | |
9 | 3000 30003000 | ≤500000 \leq 500000≤500000 | 所有 ai a_iai 相等 |
10 | 3000 30003000 | ≤500000 \leq 500000≤500000 | |
11 | 500000 500000500000 | ≤500000 \leq 500000≤500000 | 所有 ai a_iai 相等 |
12 | 500000 500000500000 | ≤500000 \leq 500000≤500000 | ai a_iai 为等差数列 |
13 | 500000 500000500000 | ≤50 \leq 50≤50 | |
14 | 500000 500000500000 | ≤3000 \leq 3000≤3000 | |
15 | 30000 3000030000 | ≤30000 \leq 30000≤30000 | |
16 | 50000 5000050000 | ≤50000 \leq 50000≤50000 | |
17 | 100000 100000100000 | ≤100000 \leq 100000≤100000 | |
18 | 200000 200000200000 | ≤200000 \leq 200000≤200000 | |
19 | 300000 300000300000 | ≤300000 \leq 300000≤300000 | |
20 | 500000 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;
}