woc    woc   woc难斩了人都傻了

害上来先看T1,发现这不就是一个小期望嘛(有啥的)真是!!打算半个小时秒掉

可是吧,读着读着题面,发现这题面有大问题,后来去找老师,还是我nb给题挑错,可是错是挑出来了,看完了题开始苦思冥想,我明白了,我不会啊!!!

随随便便打了个暴力,走人了

直接看T2,头都不带回的,看完T2,这不就是两个过程嘛,O(n2)直接搞掉,可惜我就没算这复杂度,TLE快乐30pts,这是我这整场比赛里拿的唯一的分数

然后就去看T3了,此时距离考试结束仍有2h

hhhhh,两个小时还不是拿了0分

T3相对来说还比较简单,我开始推那几种情况,有两种几乎是推出来了,可是我。。。。

卡特兰数就没学!!!!!然后改题的时候就去恶补了一下,现在还是有些了解的(看来比赛还是可以查漏补缺的hhh)

看到T4只剩下半个小时了,推T3推累了,就连想都没想就输出了个样例!!!

后来发现XIN-team算法还是很厉害的!!!(还有45pts呢。。。。)

还是时间分配有问题,下次考试一定要注意

下面是正解时间

当当当当~~~~~~有请fengwu同学为我们讲解这一套题他的思路

(据说这套题是学长出的哦)

T1 随

上来一看还是挺简单的,一个循环,暴力乘一下,也就O(nlogm)的复杂度,没想到是错的。。。

考完之后去看题解,原来是转移概率,知道了这个以后,我就开开心心的去写方程式了

写出来f[i][j]表示第 i 次乘法得到 j 的概率,然后写完了之后,我就去转移

可是考虑到m的范围过大,复杂度里要是加个m,那就必炸,,然后我就不会,就又去颓题解

题解说可以用矩阵乘

矩阵乘!!!好东西,观察式子,先不考虑操作次数,那么每次转移,都是f[ j ]转移到f[ j *a[k] ](a就是题目中的输入的数)(建议这里自己手玩一下,我弄了好长时间)

这样的话把他们两个放到一起,我们得到了一个矩阵,设他为mul[ i ][ j ]由刚才的转移我们知道mul[ j ][ j*a[k] ]+=1/n;

如果你稍微对矩阵乘法有一点点了解的话,那这里一定很好理解

循环每一个a,这样我们就可以得到一mod*mod的矩阵(因为所有的结果都要%mod,所以只可能有mod种结果,其实0转移不转移都没意思,反正全是零)

题解说这样可以拿80pts,可是我交上去只有20pts

没事继续干正解

考试的时候看到原根,就感觉这玩意没啥用,估计是一不小心放在这里的,就掠过了(就算略不过,也不会用)

接着上面的思路,利用矩阵乘,我们得到了一个O(mod*mod*mod*logm)的算法,还是不够,搬原根

对质数p的原根来说,rt的0~n-2(1~n-1也一样)次方可以取遍所有的1~n-1个数

那么原来的j就可以表示成原根形式,j*a[k]也可以,然后指数就变成了相加

j=rtw[j] ; a[k]=rtw[a[k]] ; j*a[k]=rtw[j*a[k]] ; j*a[k]=j * a[k]=rtw[j]*rtw[a[k]]=rtw[j]+w[a[k]]

这样原来的矩阵就变成了加法,然后加法就变成了二维,时间复杂度降到了O(mod*mod*logm)可以过掉本题

矩阵的时候一定得清零啊要不然会一直WA

关于原根怎么求

对于1~p中非原根的数,他的1~p-2次方中必定有1,然后就会出现循环节,而此循环节的长度又一定是p-1的因数;

那么我们可以枚举对于p-1的每一个质因数,然后p-1除以这个质因数得到一个p-1的因数

然后外层循环枚举1-p的所有数,判断有没有1的出现就ok了

最后乘起来就好了

(注意代码中num->a    ,    h->mod   ,    mod->1e9+7 )

#include<bits/stdc++.h>
using namespace std;
#define re register int
#define ll long long
const int mod=1e9+7;
const int N=100005;
int n,m,h;
int num[N];
int sum[N];
int prt,pos[N];
struct ac{
int a[1005];
friend ac operator*(ac x,ac y){
ac z;memset(z.a,0,sizeof(z.a));
//cout<<"sb"<<endl;
for(re i=0;i<h;i++)
for(re j=0;j<h;j++)
z.a[(i+j)%(h-1)]=(1ll*z.a[(i+j)%(h-1)]+1ll*x.a[i]*y.a[j]%mod)%mod;
return z;
}
}mul;
int ksm(int x,int y,int p){
int ret=1;
while(y){
if(y&1)ret=1ll*ret*x%p;
x=1ll*x*x%p;
y>>=1;
}
return ret;
}
ac ksn(ac x,int y){
ac ret;
memset(ret.a,0,sizeof(ret.a));
ret.a[0]=1;
while(y){
if(y&1)ret=ret*x;
x=x*x;
y>>=1;
}
return ret;
}
void get_prt(){
int sdk[N],tp=0;
int tmp=h-1;
for(re i=2;i*i<h;i++){
if(tmp%i==0){
sdk[++tp]=i;
while(tmp%i==0)tmp/=i;
}
}
if(tmp>1)sdk[++tp]=tmp;
for(re i=2;i<=h;i++){
int pd=0;
for(re j=1;j<=tp;j++){
if(ksm(i,(h-1)/sdk[j],h)==1){
pd=1;break;
}
}
if(pd==0){
prt=i;break;
}
}
for(re i=1;i<h-1;i++)pos[ksm(prt,i,h)]=i;
}
signed main(){
scanf("%lld%lld%lld",&n,&m,&h);
for(re i=1;i<=n;i++){
scanf("%lld",&num[i]);
sum[num[i]]++;
}
get_prt();
int mi=ksm(n,mod-2,mod);
for(re i=1;i<h;i++)mul.a[pos[i]]=1ll*sum[i]*mi%mod;
mul=ksn(mul,m);
ll ans=0;
for(re i=1;i<h;i++){
ans=(ans+1ll*i*mul.a[pos[i]]%mod)%mod;
}
printf("%lld",ans);
}

T1

然后就干完了T1

T2 单

刚看到这题我就觉得简单,嘿嘿,第一步不就n2直接上嘛

第二步不就是高斯消元吗,just-so-so,打完就跑,考完一看30pts

以为搞到了正解结果是个连暴力都算不上的暴力

我们先看第一问,给a求b

这个好说,就先不要求那个dis了,听说有人连dijstra都用上了

这样,考虑由一个点的b转移到与他相连的另一个点的b

我们设siz[i]为i的子树的权值和

那么转移时,改变的值就是这条边的两边的所有点的权值和

咱们脑子里想一想,其中一端一定是子树和,那么另一端就是siz[1]-siz[i];

现在第一种几乎已经解决了,b[son]-b[fa]=siz[1]-2*siz[son];

有这个式子,我们还需要b[1],因为他没有爹啊

但b[1]恰恰是最好求的,b[1]=siz[2]+siz[3]+siz[4]+...+siz[n];

这个式子很好想,每一个点要乘上他的距离,而这个距离在加的过程中变成了它的个数

然后我们就成功的把第一问解决掉了

-------------------------------------------------------------------------------------------------------------------------------------------

接下来是第二问,给你b求a

这个稍稍有一些难度,现在我们已经有了一个式子b[son]-b[fa]=siz[1]-2*siz[son];

我们可以根据b求出这些来,那么只要知道siz[1]就一切都解决了

siz[1]怎么求呢??

刚才还有一个式子b[1]=siz[2]+siz[3]+siz[4]+...+siz[n];

有没有恍然大悟的感觉?!直接吧上面b[son]-b[fa]=siz[1]-2*siz[son]这个式子求个和,就是把n-1对父子的b相减得到的值再相加

就得到了(n-1)*siz[1]-2*(siz[2]+siz[3]+siz[4]+...+siz[n])=tot(tot=上面的式子加和)

换一下(n-1)*siz[1]-2*b[1]=tot;

问题就迎刃而解了吧

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define re register int
const int N=1e5+10;
int T,n;
int to[N*2],nxt[N*2],head[N*2],rp;
int typ,a[N],b[N];
int dep[N],siz[N],tot;
void clear(){
rp=0;
memset(head,0,sizeof(head));
}
void add_edg(int x,int y){
to[++rp]=y;
nxt[rp]=head[x];
head[x]=rp;
}
void dfs0(int x,int f){
siz[x]=0;
siz[x]+=a[x];
for(re i=head[x];i;i=nxt[i]){
if(to[i]==f)continue;
dep[to[i]]=dep[x]+1;
dfs0(to[i],x);
siz[x]+=siz[to[i]];
}
}
void dfs1(int x,int f){
for(re i=head[x];i;i=nxt[i]){
if(to[i]==f)continue;
b[to[i]]=b[x]+siz[1]-2*siz[to[i]];
dfs1(to[i],x);
}
}
void dfs2(int x,int f){
for(re i=head[x];i;i=nxt[i]){
if(to[i]==f)continue;
tot+=b[to[i]]-b[x];
dfs2(to[i],x);
}
}
void dfs3(int x,int f){
for(re i=head[x];i;i=nxt[i]){
if(to[i]==f)continue;
siz[to[i]]=(siz[1]+b[x]-b[to[i]])/2;
if(x!=1)siz[x]-=siz[to[i]];
dfs3(to[i],x);
}
}
signed main(){
scanf("%lld",&T);
while(T--){
clear();
scanf("%lld",&n);
for(re i=1;i<n;i++){
int x,y;
scanf("%lld%lld",&x,&y);
add_edg(x,y);
add_edg(y,x);
}
scanf("%lld",&typ);
if(typ==0){
memset(b,0,sizeof(b));
for(re i=1;i<=n;i++)scanf("%lld",&a[i]);
dep[1]=0;dfs0(1,1);
for(re i=1;i<=n;i++)b[1]+=a[i]*dep[i];
dfs1(1,1);
for(re i=1;i<=n;i++)printf("%lld ",b[i]);
printf("\n");
}
else{
tot=0;
memset(siz,0,sizeof(siz));
for(re i=1;i<=n;i++)scanf("%lld",&b[i]);
dfs2(1,1);
siz[1]=(tot+2*b[1])/(n-1);
dfs3(1,1);
for(re i=2;i<=n;i++)siz[1]-=siz[i];
for(re i=1;i<=n;i++)printf("%lld ",siz[i]);
printf("\n");
}
}
}

T2

那么我们就去看T3题

这应该是四个题里面最简单的一个啦

我们直接分情况讨论

typ=0,因为我们不知道出去之后要去哪,因为没有限制,但是吧他肯定得回来

  所以向上和向下一定是相同的,向左和向右一定是相同的(这也是为什么n严格保证是偶数)

  我那知道他是竖着走还是横着走,---那就枚举呗

  我们枚举竖着走了i步,那么在竖着的方向上走的方案有C(i,i/2),横着就有C(n-i,(n-i)/2)

  最后乘上组合数C(n,i)因为你不知道是啥时候竖着啥时候横着

typ=1,这直接就是一个卡特兰数,就不说了吧

  就肯定得回来,就是进栈出栈的问题,前缀和肯定大于等于0,卡特兰数嘛!!!

typ=2,这个有点难度哦,不对不对你发现这没法直接用卡特兰数,那我们就设计dp呗

  设dp[i]表示走了i步,然后第i步回到了原点,因为我们不知道啥时候还回来过,所以要乘一个特殊的卡特兰数

  我们要从上一次回来的时候转移,所以这中间不能再回来,所以我们就先走出去一步,然后走卡特兰数,再走回来,所以这时候的卡特兰数参数要-1

  转移就好了

  对对对还有×4,毕竟有四个方向可以走啊

typ=3,这个和第一个比较类似但是他不能去负的地方,所以就是卡特兰数相乘

  然后再乘上C(n,i)

完美解决

#include<bits/stdc++.h>
using namespace std;
#define re register int
#define ll long long
const int N=100005;
const int mod=1e9+7;
int n,typ;
ll jc[N];
ll dp[N];
ll ksm(ll x,ll y){
ll ret=1;
while(y){
if(y&1)ret=ret*x%mod;
x=x*x%mod;
y>>=1;
}
return ret;
}
ll C(int x,int y){
if(x==0||y==0)return 1;
return 1ll*jc[x]*ksm(jc[y],mod-2)%mod*ksm(jc[x-y],mod-2)%mod;
}
ll cat(int x){
return 1ll*C(x<<1,x)*ksm(x+1,mod-2)%mod;
}
signed main(){
scanf("%d%d",&n,&typ);
jc[0]=jc[1]=1;
for(re i=2;i<=2*n+2;i++)jc[i]=1ll*jc[i-1]%mod*i%mod;
ll ans=0;
if(typ==0){
for(re i=0;i<=n;i+=2){
ans=(ans+C(n,i)*C(i,i>>1)%mod*C(n-i,n-i>>1)%mod)%mod;
}
}
if(typ==1){
ans=cat(n>>1);
}
if(typ==2){
dp[0]=1;
for(re i=2;i<=n;i+=2){
for(re j=2;j<=i;j+=2){
dp[i]=(1ll*dp[i]+dp[i-j]*4%mod*cat(j/2-1)%mod)%mod;
}
}
ans=dp[n];
}
if(typ==3){
for(re i=0;i<=n;i+=2){
ans=(ans+C(n,i)*cat(i>>1)%mod*cat(n-i>>1)%mod)%mod;
}
}
printf("%lld",ans);
}

T3

T4大佬

我是脑残吗我最后一题连暴力都不打就走,输出样例就走了

说实话看到题解的时候我蒙了一会

但是还是想明白了

你死不死只跟大佬嘲讽你和刷题有关

所以我们可以去dp了

找到可以利用的最多的天数D

然后暴搜,找到所有的二元组,打出的攻击+所需的天数

这里用到了一个hash其实没啥用就是快点

然后就完了

我们可以一下把大佬搞死,也可以两下,然后要打到他的血比我剩余的时间少,但是比打出的伤害多

然后看代码吧

#include<bits/stdc++.h>
using namespace std;
#define re register int
const int N=105;
const int mod=1e6+9;
int n,m,mc;
int a[N],w[N],c[N],mx;
int f[N][N];
int D,cnt;
pair<int,int> zt[N*N*N];
struct node{
int day,fi,li;
};
struct hash{
struct link{
int x,y,nxt;
}e[N*N*N];
int head[N*N*N],rp;
void ins(int x,int y){
int tmp=(1ll*x*131+y)%mod;
e[++rp]=(link){x,y,head[tmp]};
head[tmp]=rp;
}
bool query(int x,int y){
int tmp=(1ll*x*131+y)%mod;
for(re i=head[tmp];i;i=e[i].nxt){
if(e[i].x==x&&e[i].y==y)return false;
}
return true;
}
}ma;
void bfs(){
queue<node> q;
q.push((node){1,1,0});
while(!q.empty()){
node x=q.front();
q.pop();
if(x.day==D)continue;
q.push((node){x.day+1,x.fi,x.li+1});
if(x.li>1&&1ll*x.fi*x.li<=1ll*mx&&ma.query(x.fi*x.li,x.day+1)){
q.push((node){x.day+1,x.fi*x.li,x.li});
zt[++cnt]=(pair<int,int>){x.fi*x.li,x.day+1};
ma.ins(x.fi*x.li,x.day+1);
}
}
}
signed main(){
scanf("%d%d%d",&n,&m,&mc);
for(re i=1;i<=n;i++)scanf("%d",&a[i]);
for(re i=1;i<=n;i++)scanf("%d",&w[i]);
for(re i=1;i<=m;i++){
scanf("%d",&c[i]);
mx=max(mx,c[i]);
}
for(re i=1;i<=n;i++){
for(re j=a[i];j<=mc;j++){
f[i][j-a[i]]=max(f[i][j-a[i]],f[i-1][j]+1);
f[i][min(j-a[i]+w[i],mc)]=max(f[i][min(j-a[i]+w[i],mc)],f[i-1][j]);
}
}
for(re i=1;i<=n;i++){
for(re j=0;j<=mc;j++){
D=max(D,f[i][j]);
}
}
bfs();
sort(zt+1,zt+cnt+1);
for(re i=1;i<=m;i++){
if(c[i]<=D){
puts("1");
continue;
}
int pd=0,mi=0x3f3f3f3f;
for(re j=cnt,k=1;j>=1;j--){
while(k<cnt&&zt[k].first+zt[j].first<=c[i])
mi=min(mi,zt[k].second-zt[k].first),k++;
if(mi+zt[j].second-zt[j].first+c[i]<=D){pd=1;break;}
if(zt[j].first<=c[i]&&c[i]-zt[j].first+zt[j].second<=D){pd=1;break;}
}
printf("%d\n",pd);
}
}

T4

完结啦

在一次次考试中提升

noip模拟4[随·单·题·大佬]的更多相关文章

  1. noip模拟23[联·赛·题]

    \(noip模拟23\;solutions\) 怎么说呢??这个考试考得是非常的惨烈,一共拿了70分,为啥呢 因为我第一题和第三题爆零了,然后第二题拿到了70分,还是贪心的分数 第一题和第二题我调了好 ...

  2. noip模拟35[第一次4题·裂了]

    noip模拟35 solutions 这是我第一次这么正式的考四个题,因为这四个题都出自同一个出题人,并不是拼盘拼出来的. 但是考得非常的不好,因为题非常难而且一直想睡觉.. 有好多我根本就不会的算法 ...

  3. noip模拟6[辣鸡·模板·大佬·宝藏]

    这怕不是学长出的题吧 这题就很迷 这第一题吧,正解竟然是O(n2)的,我这是快气死了,考场上一直觉得aaaaa n2过不了过不了, 我就去枚举边了,然后调了两个小时,愣是没调出来,然后交了个暴力,就走 ...

  4. Noip模拟考第三题——饥饿游戏

    饥饿游戏 (hungry.pas/c/cpp) [问题描述] Chanxer饿了,但是囊中羞涩,于是他去参加号称免费吃到饱的“饥饿游戏”. 这个游戏的规则是这样的,举办者会摆出一排 个食物,希望你能够 ...

  5. NOIP 模拟 $13\; \text{玄学题}$

    题解 题如其名,是挺玄学的. 我们发现每个值是 \(-1\) 还是 \(1\) 只与它的次数是奇是偶有关,而 \(\sum_j^{j\le m}d(i×j)\) 又只与其中有多少个奇数有关 对于 \( ...

  6. NOIP 模拟 $13\; \text{工业题}$

    题解 本题不用什么推式子,找规律(而且也找不出来) 可以将整个式子看成一个 \(n×m\) 矩阵 考虑 \(f_{i,j}\),它向右走一步给出 \(f_{i,j}×a\) 的贡献,向下走一步给出 \ ...

  7. NOIP模拟13「工业题·卡常题·玄学题」

    T1:工业题 基本思路   这题有一个重要的小转化: 我们将原来的函数看作一个矩阵,\(f(i,j-1)*a\)相当于从\(j-1\)向右走一步并贡献a,\(f(i-1,j)*b\)相当于从\(i-1 ...

  8. 5.23考试总结(NOIP模拟2)

    5.23考试总结(NOIP模拟2) 洛谷题单 看第一题第一眼,不好打呀;看第一题样例又一眼,诶,我直接一手小阶乘走人 然后就急忙去干T2T3了 后来考完一看,只有\(T1\)骗到了\(15pts\)[ ...

  9. noip模拟26[肾炎黄·酱累黄·换莫黄]

    \(noip模拟26\;solutions\) 这个题我做的确实是得心应手,为啥呢,因为前两次考试太难了 T1非常的简单,只不过我忘记了一个定理, T2就是一个小小的线段树,虽然吧我曾经说过我再也不写 ...

随机推荐

  1. 04- HTML常用标签

    HTML标签分类 通过上节博客我们知道了网页的组成:文字 图片 连接 视频 音频.在HTML页面中,带有"< >"符号的元素被称为HTML标签,如上面提到的 <H ...

  2. hdu1686 最大匹配次数 KMP

    题意:      给你两个串,问你串a在串b中出现了多少次. 思路:       直接匹配,KMP时匹配到匹配串的最后一个的时候不用跳出,直接匹配就行了,最后一个'/0'不会和目标串匹配,所以经过ne ...

  3. Linux中常见的150个命令(干货)

    目录 线上查询及帮助命令 文件和目录操作命令 查看文件和内容处理命令 文件压缩及解压缩命令 信息显示命令 搜索文件命令 进程管理相关命令 用户管理命令 基础网络操作命令 深入网络操作命令 有关磁盘与文 ...

  4. 使用 Azure Container Registry 储存镜像

    Azure Container Registry(容器注册表)是基于 Docker Registry 2.0规范的托管专用 Docker 注册表服务. 可以创建和维护 Azure 容器注册表来存储与管 ...

  5. 基于RRCF(robust random cut forest)的时间序列异常检测流程

    摘要:RRCF是亚马逊提出的一个流式异常检测算法,是对孤立森林的改进,可对时序或非时序数据进行异常检测.本文是我从事AIOps研发工作时所做的基于RRCF的时序异常检测方案. 1.      数据格式 ...

  6. java 运用Cipher加密再解密后会变乱码。解决方案!

    同样的方法类用main调用加解密都正常,就是当用到业务就是加密后再解密变乱码. 后来发现同样的内容加密后的内容竟不相同. 经调试发现 encryptData.getBytes() 转为字节是的使用 C ...

  7. JavaSE全部学习笔记——集合

  8. 【js】Leetcode每日一题-二叉树的堂兄弟节点

    [js]Leetcode每日一题-二叉树的堂兄弟节点 [题目描述] 在二叉树中,根节点位于深度 0 处,每个深度为 k 的节点的子节点位于深度 k+1 处. 如果二叉树的两个节点深度相同,但 父节点不 ...

  9. [bug] Python Virtualenv 安装失败:ERROR: Cannot uninstall 'filelock'.

    参考 https://my.oschina.net/gain/blog/4333100

  10. [其他] vscode 快速教程

    概述 vs:集成开发环境,包括软件生命周期中需要的大部分工具,如UML,代码管控,IDE等 vs code:代码编辑器,支持插件扩展,对网页和云端开发做了优化 快捷键 F1/ctrl+shift+p: ...