退役IV次后做题记录
退役IV次后做题记录
我啥都不会了。。。。
AGC023 D
如果所有的楼房都在\(S\)同一边可以直接得出答案。
否则考虑最左最右两边的票数,如果左边>=右边,那么最右边会投给左边,因为就算车往右开,只要没走到最左边,最后也要折回左边,所以不如先走完左边然后直接过来。左边<右边一样。
然后递归下去变成了一个子问题,可以看做一边的票数+=另一边,然后删除另一边。
AGC023 E
考虑枚举两个位置\(i,j\)计算这两个位置产生逆序对的排列数量。
如果\(A_i=A_j\)很好算,方案数都是对称的,就是总的排列数/2。
总的排列数计算方法:设\(C_i=\sum_{j=1}^n[A_j\ge i],sum=\Pi_{i=1}^n(C_i-n+i)\)
如果\(A_i<A_j\)也很好算,如果\(P_j\)取\(>A_i\)的值显然没有贡献,所以将\(A_j\)强制设为\(A_i\)再算即可,变成上面的情况
因为减少了一个\(A\),所以会减少一段\(C\),也就是排列的数量会变,乘一个\(\Pi\frac{C_i-n+i-1}{C_i-n+i}\)
设\(d_i=\frac{C_i-n+i-1}{C_i-n+i}\),也就是会乘一段\(d\),但是\(d\)有\(0\)不能直接前缀鸡所以分段搞一下就行了。
如果\(A_i>A_j\)正难则反考虑用总方案-没有逆序对的方案数,这个就是将\(A_i\)强制设为\(A_j\)后总排列数/2,和上面一样,也是对\(d\)分段搞。
AGC023 F
先考虑有一堆序列,怎么拼成一段最优的序列,推推式子就知道答案是按照\(cnt_0/cnt_1\)从大到小选
然后搬到树上来,也是对的,就是每次选一个\(cnt_0/cnt_1\)最小的点,将这个点现在的序列合并到其父亲
(虽然感觉很玄学但却是就是对的。。。
loj2409
qwq多项式都不会打了qwq
计算\(F(x)=\sum x^if_i\)
\(=\sum_{i=1}^nx^i\sum_{j=1}^na_j^i\)
\(\sum_{j=1}^n\sum_{i=1}^nx^ia_j^i\)
\(\sum_{i=1}^n\frac{1}{1-a_ix}\)
然后这个可以分治通分跑了qwq但是常数很大qwq然后就神仙了qwq
\(\sum_{i=1}^n1-\frac{a_ix}{1-a_ix}\)
\(n-x\sum_{i=1}^n\frac{a_i}{1-a_ix}\)
我也不知道怎么就能看出来这里可以积分了qwq
\(n-x\sum_{i=1}^n(\ln(1-a_ix))'\)
\(n-x(\ln\Pi_{i=1}^n(1-a_ix))'\)
就可以较快地分治ntt做了qwq好牛批啊qwq
bzoj3462
首先\(S\)肯定是\(\Pi p_i\)的形式(\(p\)互不相同)
然后就变成了一个背包
将\(n\)减去\(\sum p\),就变成了一个完全背包方案数
然后我发现我不会
这题还有一个性质就是\(p\)是\(S\)约数所以很优秀
设\(n=\sum p_ic_i,P_i=S/p_i\),将\(c_i\)拆成\(xP_i+y\)的形式,其中\(y<P_i\),那么实际上\(p_iP_ix\)就是\(S\)倍数了,后面的\(p_iy\)就小于\(S\)了于是可以枚举有多少个整的\(S\),分配给\(m\)个质数,剩下的做一个完全背包
#include<bits/stdc++.h>
#define mod 1000000007
typedef long long ll;
ll gi(){
ll x=0,f=1;
char ch=getchar();
while(!isdigit(ch))f^=ch=='-',ch=getchar();
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return f?x:-x;
}
int p[10],m,bag[14000010],_bag[14000010],inv[10],ifact;
int C(ll n,int m){
int ret=ifact;
for(int i=0;i<m;++i)ret=(n-i)%mod*ret%mod;
return ret;
}
int Get(ll n,int m){return n?C(n+m-1,m-1):1;}
int main(){
#ifdef XZZSB
freopen("in.in","r",stdin);
freopen("out.out","w",stdout);
#endif
int S=gi(),q=gi();
for(int i=2,s=S;i<=s;++i)
if(s%i==0){
s/=i;p[++m]=i;
if(s%i==0){while(q--)puts("0");return 0;}
}
int N=m*S,sum=0;
bag[0]=1;
for(int _=1,x;_<=m;++_){
x=p[_];sum+=x;
memcpy(_bag,bag,sizeof bag);
for(int i=1;i<=x;++i){
for(int j=i,sum=i==x;j<=N;j+=x){
if(j-S>=0)sum=(sum-_bag[j-S]+mod)%mod;
bag[j]=(bag[j]+sum)%mod;
sum=bag[j];
}
}
}
inv[1]=1;for(int i=2;i<=m;++i)inv[i]=mod-1ll*inv[mod%i]*(mod/i)%mod;
ifact=1;for(int i=2;i<m;++i)ifact=1ll*ifact*inv[i]%mod;
while(q--){
ll n=gi();int ans=0;if(n<sum){puts("0");continue;}
n-=sum;
for(int i=0,lim=std::min(n/S,m-1ll);i<=lim;++i)
ans=(ans+1ll*Get(n/S-i,m)*bag[n%S+S*i])%mod;
printf("%d\n",ans);
}
return 0;
}
bzoj3481
枚举一个数\(x\),要求满足\(xy\equiv Q(\mod P)\)的\(y\)数量
也就是满足\(Ax+Py=Q\)的\(x\)数量
根据exgcd的理论,首先当\(Q\)是\(\gcd(A,P)\)倍数时才有解,然后每隔\(P/\gcd(A,P)\)会出现一个\(x\),也就是\([0,P)\)中解的数量就是\(\gcd(A,P)\)
答案就是\(\sum_{i=0}^{P-1}\gcd(i,P)[\gcd(i,P)|Q]\)
再推推就是\(\sum_{d|P,d|Q}^{P-1}d\cdot\varphi(\frac Pd)\)
然后用pr分解一下。。。(pr都不会写了kk)
#include<bits/stdc++.h>
typedef long long ll;
#define mod 1000000007
ll gi(){
ll x=0,f=1;
char ch=getchar();
while(!isdigit(ch))f^=ch=='-',ch=getchar();
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return f?x:-x;
}
ll mul(ll x,ll y,ll mo){
ll r=x*y-(ll)((long double)x/mo*y)*mo;
return(r%mo+mo)%mo;
}
ll pow(ll x,ll y,ll mo){
ll ret=1;
while(y){
if(y&1)ret=mul(ret,x,mo);
x=mul(x,x,mo);y>>=1;
}
return ret;
}
bool MR(ll x){
static int pr[]={2,3,5,61,23333,19260817};
if(x==1)return 0;
for(int i=0;i<6;++i)if(x==pr[i])return 1;
int t=0;
ll _=x-1;
while(~_&1)_>>=1,++t;
for(int i=0;i<6;++i){
ll s=pow(pr[i],_,x);
if(s==1||s==x-1)continue;
int T=t;
while(T--){
s=mul(s,s,x);
if(s==x-1)break;
}
if(T==-1)return 0;
}
return 1;
}
int PRC;ll PRX;
ll f(ll y){return(mul(y,y,PRX)+PRC)%PRX;};
ll PR(ll x){
if(~x&1)return 2;
PRX=x;
PRC=rand()%(x-1)+1;
ll a=rand()%x,b=a;
int i=1,s=2;
for(;;){
ll y=std::__gcd(llabs(b-a),x);
if(y>1&&y<x)return y;
a=f(a);
if(a==b)return 1;
if(++i==s)b=a,s<<=1;
}
}
int iP[10010],pE[10010],qE[10010],m,xP[10010];
std::map<ll,int>M;
void fact(ll x,int*E){
if(x==1)return;
if(MR(x)){if(!M.count(x))M[x]=++m,xP[m]=x%mod;++E[M[x]];return;}
ll y;while(y=PR(x),y==1);
fact(y,E),fact(x/y,E);
}
int ans;
int main(){
#ifdef XZZSB
freopen("in.in","r",stdin);
freopen("out.out","w",stdout);
#endif
srand(19260817);
int n=gi();
int P=1,Q=1;ll x;
for(int i=1;i<=n;++i)x=gi(),P=x%mod*P%mod,fact(x,pE);
for(int i=1;i<=n;++i){
x=gi();
if(!x){
memcpy(qE,pE,sizeof pE);
break;
}
Q=x%mod*Q%mod,fact(x,qE);
}
for(int i=1;i<=m;++i)iP[i]=pow(xP[i],mod-2,mod);
for(int i=1;i<=m;++i)qE[i]=std::min(qE[i],pE[i]);
ans=P;
for(int i=1;i<=m;++i)ans=1ll*ans*((pE[i]==qE[i])+1ll*(qE[i]+1-(pE[i]==qE[i]))*(xP[i]-1)%mod*iP[i]%mod)%mod;
printf("%d\n",ans);
return 0;
}
bzoj3512
\(\sum_{i=1}^n\sum_{j=1}^m\varphi(ij)\)
\(=\sum_{i=1}^n\sum_{j=1}^m\varphi(i)\varphi(j)f(\gcd(i,j))\)
这里\(f(x)=\frac{x}{\varphi(x)}\)
用一些套路的推法,\(=\sum_{i=1}^n\varphi(i)\sum_{d|i}f(d)\sum_{j=1}^m\varphi(j)[\gcd(i,j)=d]\)
构造\(g(x)\)使得\(\sum_{d|n}g(d)=f(n)\)(n在1e5范围所以直接减就行了)
\(=\sum_{i=1}^n\varphi(i)\sum_{d|i}g(d)\sum_{d|j}^m\varphi(j)\)
\(=\sum_{d=1}^ng(d)\left(\sum_{d|i}^n\varphi(i)\right)\left(\sum_{d|j}^m\varphi(j)\right)\)
然后这个形式就很优秀了,现在要求\(\sum_{d|x}^n\varphi(x)\)
怎么求呢?我不会。。。然后瞎b推
\(=\varphi(d)\sum_{i=1}^{n/d}\varphi(i)f(\gcd(i,d))\)
\(=\varphi(d)\sum_{j|d}^{n/d}f(j)\left(\sum_{j|i}^{n/d}\varphi(i)\right)\)
然后后面这部分怎么又是这个形式了。。就写个递归
然后跑的飞快???
#include<bits/stdc++.h>
typedef long long ll;
#define mod 1000000007
ll gi(){
ll x=0,f=1;
char ch=getchar();
while(!isdigit(ch))f^=ch=='-',ch=getchar();
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return f?x:-x;
}
int pow(int x,int y){
int ret=1;
while(y){
if(y&1)ret=1ll*ret*x%mod;
x=1ll*x*x%mod;y>>=1;
}
return ret;
}
const int N=5000000;
int pr[N+10],phi[N+10],sphi[N+10],P,s[N+10];
bool yes[N+10];
int Phi(int x){
if(x<=N)return sphi[x];
int ret=1ll*x*(x+1)/2%mod;
for(int l=2,r;l<=x;l=r+1)r=x/(x/l),ret=(ret-1ll*Phi(x/l)*(r-l+1)%mod+mod)%mod;
return ret;
}
int dPhi(int x,int n){//\sum_{x|i}^n\varphi(x)
if(x==1)return Phi(n);
if(n<x)return 0;
int ret=0;
for(int i=1;i*i<=x;++i)
if(x%i==0){
ret=(ret+1ll*s[i]*dPhi(i,n/x))%mod;
if(i*i<x)ret=(ret+1ll*s[x/i]*dPhi(x/i,n/x))%mod;
}
return 1ll*ret*phi[x]%mod;
}
int main(){
#ifdef XZZSB
freopen("in.in","r",stdin);
freopen("out.out","w",stdout);
#endif
int n=gi(),m=gi();
for(int i=2;i<=N;++i){
if(!yes[i])pr[++P]=i,phi[i]=i-1;
for(int j=1;j<=P&&i*pr[j]<=N;++j){
yes[i*pr[j]]=1;
if(i%pr[j]==0){
phi[i*pr[j]]=phi[i]*pr[j];
break;
}
phi[i*pr[j]]=phi[i]*(pr[j]-1);
}
}
phi[1]=1;
for(int i=1;i<=n;++i)s[i]=1ll*i*pow(phi[i],mod-2)%mod;
for(int i=2;i<=n;++i){
for(int j=1;j*j<=i;++j)
if(i%j==0){
s[i]=(s[i]-s[j]+mod)%mod;
if(j!=1&&j*j!=i)s[i]=(s[i]-s[i/j]+mod)%mod;
}
}
for(int i=1;i<=N;++i)sphi[i]=(phi[i]+sphi[i-1])%mod;
int ans=0;
for(int i=1;i<=n;++i)ans=(ans+1ll*s[i]*dPhi(i,n)%mod*dPhi(i,m))%mod;
printf("%d\n",ans);
return 0;
}
bzoj3560
显然可以质因子分开算,然后直接算就行了= =
#include<bits/stdc++.h>
typedef long long ll;
#define mod 1000000007
ll gi(){
ll x=0,f=1;
char ch=getchar();
while(!isdigit(ch))f^=ch=='-',ch=getchar();
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return f?x:-x;
}
int pr[666010],P,d[10000010],pd[10000010],sd[10000010];
std::vector<int>vec[666010];
bool yes[10000010];
int pp[100];
int main(){
#ifdef XZZSB
freopen("in.in","r",stdin);
freopen("out.out","w",stdout);
#endif
int n=gi(),N=10000000;
for(int i=2;i<=N;++i){
if(!yes[i])pr[++P]=i,pd[i]=i,d[i]=P,sd[i]=1;
for(int j=1;j<=P&&i*pr[j]<=N;++j){
yes[i*pr[j]]=1;d[i*pr[j]]=j;
if(i%pr[j]==0){
pd[i*pr[j]]=pd[i]*pr[j];
sd[i*pr[j]]=sd[i]+1;
break;
}
pd[i*pr[j]]=pr[j];
sd[i*pr[j]]=1;
}
}
for(int i=1,x;i<=n;++i){
x=gi();
while(x>1)vec[d[x]].push_back(sd[x]),x/=pd[x];
}
int ans=1;
for(int i=1;i<=P;++i){
if(vec[i].empty())continue;
int k=1,y=pr[i];
pp[0]=1;pp[1]=y;
while(1ll*pp[k]*y<=N)pp[k+1]=pp[k]*y,++k;
for(int j=1;j<=k;++j)pp[j]=(pp[j]+pp[j-1])%mod;
int res=0;
for(int j=0,x;j<vec[i].size();++j){
x=vec[i][j];
res=(1ll*res*pp[x]+pp[x-1]*(y-1))%mod;
}
ans=1ll*ans*(res+1)%mod;
}
printf("%d\n",ans);
return 0;
}
退役IV次后做题记录的更多相关文章
- 退役III次后做题记录(扯淡)
退役III次后做题记录(扯淡) CF607E Cross Sum 计算几何屎题 直接二分一下,算出每条线的位置然后算 注意相对位置这个不能先搞出坐标,直接算角度就行了,不然会卡精度/px flag:计 ...
- 退役II次后做题记录
退役II次后做题记录 感觉没啥好更的,咕. atcoder1219 历史研究 回滚莫队. [六省联考2017]组合数问题 我是傻逼 按照组合意义等价于\(nk\)个物品,选的物品\(\mod k\) ...
- Sam做题记录
Sam做题记录 Hihocoder 后缀自动机二·重复旋律5 求一个串中本质不同的子串数 显然,答案是 \(\sum len[i]-len[fa[i]]\) Hihocoder 后缀自动机三·重复旋律 ...
- FJOI2017前做题记录
FJOI2017前做题记录 2017-04-15 [ZJOI2017] 树状数组 问题转化后,变成区间随机将一个数异或一,询问两个位置的值相等的概率.(注意特判询问有一个区间的左端点为1的情况,因为题 ...
- UOJ 做题记录
UOJ 做题记录 其实我这么弱> >根本不会做题呢> > #21. [UR #1]缩进优化 其实想想还是一道非常丝播的题目呢> > 直接对于每个缩进长度统计一遍就好 ...
- project euler做题记录
ProjectEuler_做题记录 简单记录一下. problem 441 The inverse summation of coprime couples 神仙题.考虑答案为: \[\begin{a ...
- BJOI做题记录
BJOI做题记录 终于想起还要做一下历年省选题了2333 然而咕了的还是比做了的多2333 LOJ #2178. 「BJOI2017」机动训练 咕了. LOJ #2179. 「BJOI2017」树的难 ...
- [日记&做题记录]-Noip2016提高组复赛 倒数十天
写这篇博客的时候有点激动 为了让自己不颓 还是写写日记 存存模板 Nov.8 2016 今天早上买了两个蛋挞 吃了一个 然后就做数论(前天晚上还是想放弃数论 但是昨天被数论虐了 woc noip模拟赛 ...
- noip做题记录+挑战一句话题解?
因为灵巧实在太弱辽不得不做点noip续下命QQAQQQ 2018 积木大赛/铺设道路 傻逼原题? 然后傻逼的我居然检查了半天是不是有陷阱最后花了差不多一个小时才做掉我做过的原题...真的傻逼了我:( ...
随机推荐
- ML学习笔记之LATEX数学公式基本语法
作者:@houkai本文为作者原创,转载请注明出处:https://www.cnblogs.com/houkai/p/3399646.html 0x00 概述 TEX 是Donald E. Knuth ...
- python基础04day
一 引子 数据类型 用途 定义方式 是否多项 有/无序 可/不可变 对应状态 数字 否 —— 不可 字符串 “”‘’“““””” 否 有 不可 列表 [] 是 有 可 同 ...
- 连接池未注册org.logicalcobwebs.proxool.ProxoolException: Attempt to refer to a unregistered pool by its alias 'XXX'
代码之前一直好好的,写了一个定时器后报错,本地测试为了立马能执行就用cron表达式* * * * * ?,为了只执行一次在最后面加上Thread.sleep(1000*3600*24)睡眠二十四小时从 ...
- 关于vscode自动跳转回车的解决方法(关闭vscode自动保存功能;可能和其他插件有冲突)
关于vscode自动跳转回车的解决方法(关闭vscode自动保存功能:可能和其他插件有冲突)
- 【转载】Windows系统电脑通过命令msinfo32查看系统信息
在Windows操作系统中,可以使用msinfo32的操作命令查看操作系统相关信息,通过msinfo32命令可以查看到系统摘要,包括硬件资源.组件.软件环境等系统信息.其中系统摘要包括冲突/共享.DM ...
- 为元素添加 title 属性
---恢复内容开始--- 可以使用title属性(不要与title元素混淆)为网站上任何部分加上提示标签. ... <ul title="Table of Contents" ...
- 33、vue中的事件修饰符.stop、.prevent、.self、.capture、.once
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- Java 之 ArrayList 集合
一.ArrayList 概述 java.util.ArrayList 是 大小可变的数组 的实现,存储在内的数据称为元素.该类是一个 集合类(容器),可以让我们更便捷的存储和操作对象数据. 该类可以 ...
- idea注释类,方法
1.添加类注释:file-settings-file and code Templates-Class #if (${PACKAGE_NAME} && ${PACKAGE_NAME} ...
- windows定时器编程
目前,Windows下的定时器编程主要有三种方式. 1)SetTimer定时器是利用Windows窗口消息WM_TIMER来实现的.使用方法非常简单,SetTimer创建定时器,KillTimer销毁 ...