[考试反思]0321省选模拟51:直觉

$whzzt$这个出题人我记住了。。。7场之前刚见过他。。。

目前做过的他出的$5$道题,得分$0+5+0+1+0$

怎么搞得跟满分$10$分一样。。。

得亏今天$T3$是原题。不然总分又是个位数。

一只老虎一棵蒜,爆零爆的团团转。

 

的确感觉$T2$比较简单,但神$**$的这居然是个结论题。

我在那里想了不知道多久做法,然而想了半天居然是个极其简单的结论(然而证明还挺奇怪

大神们都直觉秒结论。$66$分搜索拿$bitset$一压就没了。

然后我花了$3h$想方设法优化暴力算法,最后剪枝挂了$11 \rightarrow 0$。

没办法了。这就是看命了。

结果被$T2$吃了大量时间而一无所获的我去看了下$T3$,发现好像可以比较直观的理解。

然而剩下的时间不多,于是暴写,一遍过样例,花了差不多半小时,就剩下$4$分钟,吓死我。

生死时速,$0pts$和$101pts$的区别。(有了最后$4min$才去把$T1$的签到拿下,然而$5pts$暴力没时间写了

 

T1:数学

大意:给定$a,n,b,m$满足$a^n \equiv -1(mod \ m),b^n \equiv -1 (mod \ m)$求$c$满足$c^2 \equiv ab (mod \ m)$。多测。$T \le 10000,n,m,a,b \le 10^{18}$

大概是个构造公式的题。

老套路,想办法减小数据规模递归下去。

先考虑一些别的情况,如果$n$是奇数那么一个可行的答案就是$(ab)^{frac{n+1}{2}}$

如果$m$是偶数那么可以直接提出$2$。

如果$m$是$4$的倍数,那么显然不存在合法的$a,b$。不可能。

所以只要考虑$m$是奇数。

然后就是完全想不到的了,一堆设列公式:(题解还有锅

如果$y_0^{2w}=1$那么移项并且平方差得到$(y_0^{w}-1)(y_0^{w}+1) \equiv 0$

然后$m$对二者分别取$gcd$。显然没有交,但是为什么并起来恰好是$m$就不得而知了。(题解也不说

然后就递归求解再$CRT$回来。复杂度是$O(Tlog^2m)$的。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 ll mul(ll x,ll y,ll m,ll a=0){
 5     if(x<1<<30&&y<1<<30)return x*y%m;
 6     for(;y;y>>=1,x<<=1,x=x>=m?x-m:x)if(y&1)a+=x,a=a>=m?a-m:a;
 7     return a;
 8 }
 9 ll qp(ll b,ll t,ll m,ll a=1){for(;t;t>>=1,b=mul(b,b,m))if(t&1)a=mul(a,b,m);return a;}
10 ll gcd(ll x,ll y){return y?gcd(y,x%y):x;}
11 void exgcd(ll a,ll b,ll&x,ll&y){
12     if(!b){x=1;y=0;return;}
13     exgcd(b,a%b,y,x);y-=a/b*x;
14 }
15 ll inv(ll x,ll m){ll a,b;exgcd(x,m,a,b);return (a%m+m)%m;}
16 ll CRT(ll a,ll m,ll A,ll M){return (mul(mul(a,inv(M,m),m),M,m*M)+mul(mul(A,inv(m,M),M),m,m*M))%(m*M);}
17 ll solve(ll a,ll b,ll n,ll m){a%=m;b%=m;
18     if(n&1)return qp(mul(a,b,m),n+1>>1,m);
19     if(m<=2)return m-1;
20     if(m&1^1)return m>>=1,CRT(solve(a,b,n,2),2,solve(a,b,n,m),m); 
21     ll N=n; int c=0; while(N&1^1)N>>=1,c++; 
22     ll r=qp(a,N,m),c0=qp(mul(a,b,m),N+1>>1,m),y0=qp(mul(a,b,m),N,m);
23     vector<ll>pw(c+1); for(int i=0;i<=c;++i)pw[i]=r,r=mul(r,r,m);
24     while(c){
25         int w=0; ll X; for(ll x=y0;x!=1;++w)X=x,x=mul(x,x,m); 
26         w--; if(w<0)break;
27         if(X!=m-1){ll m1=gcd(m,X-1),m2=gcd(m,X+1);return CRT(solve(a,b,n,m1),m1,solve(a,b,n,m2),m2);}
28         c0=mul(c0,pw[c-w-1],m); y0=mul(y0,pw[c-w],m);
29     }return c0;
30 }
31 main(){ll a,b,n,m,t,id;cin>>t>>id;while(t--)scanf("%lld%lld%lld%lld",&a,&b,&n,&m),printf("%lld\n",solve(a,b,n,m));}
要想到这个还得修炼八百年

 

T2:灌水

大意:给定数列$a$,求对于所有排列$p$的$\sum\limits_{i=1}^{n} min(max(a_j[j\le i]),max(a_j[j \ge i])) -a_i$有哪些可能值。$n \le 1000,a_i \le 100$

结论是:对于每个$a_i$它都可能产生任意$a_j \geq a_i$的$a_j > a_i$。(除了$a_j$是唯一最大值)。互不干扰可以直接叠加。

大概是可证的,就是可以通过交换二者位置。这种结论你猜不出来证它干啥。

然后这题就只剩下背包了。唯一需要想的就是需要$bitset$一下。复杂度$O(\frac{n^2l^2}{32})$。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 bitset<100001>B,R;
 4 int n,a[1111],y[111];
 5 int main(){
 6     cin>>n;
 7     for(int i=1;i<=n;++i)scanf("%d",&a[i]),y[a[i]]++;
 8     sort(a+1,a+1+n); reverse(a+1,a+n+1); y[a[1]]--;    B=1;
 9     for(int i=2;i<=n;++i){
10         for(int j=a[i]+1;j<=100;++j)if(y[j])R|=B<<j-a[i];
11         B|=R;R.reset();
12     }for(int i=0;i<=100000;++i)if(B[i])printf("%d ",i);
13 }
好久没写过这么短的了。。。纯结论没代码没思维的题,我真不知道怎么做了。。。

 

T3:C

大意:环上等距有$n$个等质量质点。有些脱落了。求最少再脱落几个能使重心回到环中心。$n \le 20000$。$n$最多有$2$种质因子。

$2$自然会是关键点。

按照重心的定义,发现重心是带权可加的。所以我们可以把整个环拆成若干集合,使每个集合的重心都在环中心就好。

只有$1$种质因子的话,编号模$\frac{n}{p}$相同的点合并为一个集合一定是最优的。(其余合并方法均可以拆分)线性判断即可。

否则,每个点属于两个集合,但它同时只能存在于一个集合内,最大独立集,最大权闭合子图,没了。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define Sz 233333
 4 int k,n,a,b,ban[Sz],A,B,S,T,BAN[Sz],q[Sz],d[Sz],fir[Sz],l[Sz],to[Sz],v[Sz],ec;
 5 void link(int a,int b,int w){l[++ec]=fir[a];fir[a]=ec;to[ec]=b;v[ec]=w;}
 6 void con(int a,int b,int w){link(a,b,w);link(b,a,0);}
 7 bool bfs(){
 8     for(int i=0;i<=T;++i)d[i]=Sz;d[S]=1;q[1]=S;
 9     for(int h=1,t=1;h<=t;++h)for(int i=fir[q[h]];i;i=l[i])if(d[to[i]]>d[q[h]]+1&&v[i])
10         d[q[++t]=to[i]]=d[q[h]]+1;
11     return d[T]!=Sz;
12 }
13 int dfs(int p,int f){int r=f;
14     if(p==T)return f;
15     for(int i=fir[p];i&&r;i=l[i])if(d[to[i]]==d[p]+1&&v[i]){
16         int x=dfs(to[i],min(r,v[i]));
17         if(!x)d[to[i]]=-1;
18         v[i]-=x;v[i^1]+=x;r-=x;
19     }return f-r;
20 }
21 int main(){int t;cin>>t;while(t--){
22     
23     cin>>n>>k; a=b=0;
24     int x=n;
25     for(int i=2;i*i<=x;++i)if(x%i==0){
26         if(!b)a=i,A=n/a;else b=i,B=n/b;
27         while(x%i==0)x/=i;
28         break;
29     }if(x>1)if(!a)a=x,A=n/a;else b=x,B=n/b;
30     if(!b){
31         int ans=0;
32         for(int i=0;i<A;++i)ban[i]=0;
33         for(int i=1,x;i<=k;++i)scanf("%d",&x),ban[(x-1)%A]=1;
34         for(int i=0;i<A;++i)ans+=ban[i]?0:a;
35         cout<<(ans?n-k-ans:-1)<<endl;
36     }else{
37         S=A+B;T=S+1;int ans=0;
38         for(int i=0;i<A;++i)ban[i]=0;
39         for(int i=0;i<B;++i)BAN[i]=0;
40         for(int i=1,x;i<=k;++i)scanf("%d",&x),x--,ban[x%A]=1,BAN[x%B]=1;
41         ec=1; for(int i=0;i<=T;++i)fir[i]=0;
42         for(int i=0;i<A;++i)if(!ban[i])con(S,i,a),ans+=a;
43         for(int i=0;i<B;++i)if(!BAN[i])con(i+A,T,b),ans+=b;
44         for(int i=0;i<n;++i)con(i%A,A+i%B,Sz);
45         while(bfs())ans-=dfs(S,n);
46         cout<<(ans?n-k-ans:-1)<<endl;
47     }
48     
49 }}
View Code

 

posted @ 2020-03-21 22:02  DeepinC  阅读(250)  评论(0编辑  收藏  举报