2018.9.12 離線賽 by CalvinJin
阿新 • • 發佈:2018-12-09
T1——gcd(3915)
Description:
給你兩個數,,求.特殊地,.
Solution:
- 關於此題,不知道是被題面誤導要因式分解,還是被NOIP2017D1T1所敏感地去打表…
- 反正一開始就沒想到正解上,接近自閉…
- 但當開始走投無路的去肉模擬這個玩意的時候,發現推了一次得到,就感覺這個好像就是將肉拆一次,再次…
- 真的無語…有點腦筋急轉彎的味道…
Code:
#include<bits/stdc++.h>
using namespace std;
#define REP(i,f,t)for(int i=(f),i##_end_=(t);i<=i##_end_;++i)
#define SREP(i,f,t)for(int i=(f),i##_end_=(t);i<i##_end_;++i)
#define DREP(i,f,t)for(int i=(f),i##_end_=(t);i>=i##_end_;--i)
#define db double
#define ll long long
#define INF 0x3f3f3f3f
#define inf 0x3f3f3f3f3f3f3f
#define MINF 0xc0c0c0c0
#define Sz(a) sizeof(a)
#define mcl(a,b) memset(a,b,Sz(a))
#define mcp(a,b) memcpy(a,b,Sz(b))
#define pb push_back
#define fi first
#define se second
template<class T>inline bool chkmin(T &x,T y){return y<x?x=y,1:0;}
template<class T>inline bool chkmax(T &x,T y){return x<y?x=y,1:0;}
typedef pair<int,int>PII;
template<class T>inline void Rd(T &x){
x=0;char c;
while((c=getchar())<48);
do x=(x<<1)+(x<<3)+(c^48);
while((c=getchar())>47);
}
#define mod 1000000007
ll A,B,K;
ll gcd(ll x,ll y){return !y?x:gcd(y,x%y);}
struct p50{
ll Pow(ll a,ll b){
ll x=1;
while(b){
if(b&1)x=x*a%mod;
b>>=1,a=a*a%mod;
}
return x;
}
void solve(){
ll X=A-B;
ll Y=Pow(A,K)+Pow(B,K);
if(!X)printf("%lld\n",Y%mod);
else {
ll d=gcd(X,Y)%mod;
printf("%lld\n",d);
}
}
}p1;
struct p100{
ll Mul(ll x,ll y,ll P){
ll res=0;
while(y){
if(y&1)res=(res+x)%P;
y>>=1;
x=(x<<1)%P;
}
return res;
}
ll Pow(ll a,ll b,ll P){
ll x=1;
while(b){
if(b&1)x=Mul(x,a,P);
a=Mul(a,a,P);
b>>=1;
}
return x;
}
void solve(){
ll X=A-B;
if(!X)printf("%lld\n",(Pow(A,K,mod)+Pow(B,K,mod))%mod);
else {
ll Y=(Pow(A,K,X)+Pow(B,K,X))%X;
printf("%lld\n",gcd(X,Y)%mod);
}
}
}p2;
int main(){
// freopen("gcd.in","r",stdin);
// freopen("gcd.out","w",stdout);
Rd(A),Rd(B),Rd(K);
if(A<=9 && B<=9 && K<=9)p1.solve();
else p2.solve();
return 0;
}
T2——triangle(3916)
Description:
有一個長度為的序列{},表示木棒的長度.我們將用這些木棒拼出周長最大的三角形. 那麼有個操作.
- ,,.將
- ,l,r.對區間進行詢問最大的三角形周長.
Solution:
- 對於三角形的周長問題,最近也是頻繁遇到.
- 而此題是帶單點修改的.那麼顯然是用線段樹解決.
- 那麼線段樹的關鍵還是合併問題.
- 我們發現,在樹上直接存答案是不太現實的.
- 那麼我們只能是存該區間的一些木棒.
- 而我們要的是最大的周長,那麼關鍵字一定是.
- 這裡,我覺得自己的做法還是偏無腦的做法.
- 因為分析修改的,對於每個區間影響的,其實是隻有個.
- 那麼我們就在樹上存上每個區間的前大即可.
- 最後詢問暴力來取.
Code:
#include<bits/stdc++.h>
using namespace std;
#pragma GCC optimize("Ofast")
#define REP(i,f,t)for(int i=(f),i##_end_=(t);i<=i##_end_;++i)
#define SREP(i,f,t)for(int i=(f),i##_end_=(t);i<i##_end_;++i)
#define DREP(i,f,t)for(int i=(f),i##_end_=(t);i>=i##_end_;--i)
#define db double
#define ll long long
#define INF 0x3f3f3f3f
#define inf 0x3f3f3f3f3f3f3f
#define MINF 0xc0c0c0c0
#define Sz(l) sizeof(l)
#define mcl(l,b) memset(l,b,Sz(l))
#define mcp(l,b) memcpy(l,b,Sz(b))
#define pb push_back
#define fi first
#define se second
template<class T>inline bool chkmin(T &x,T y){return y<x?x=y,1:0;}
template<class T>inline bool chkmax(T &x,T y){return x<y?x=y,1:0;}
typedef pair<int,int>PII;
template<class T>inline void Rd(T &x){
x=0;char c;
while((c=getchar())<48);
do x=(x<<1)+(x<<3)+(c^48);
while((c=getchar())>47);
}
#define N 100002
int n,q;
int A[N];
struct p40{
int tmp[N],cnt;
void solve(){
int op,a,b;
ll ans;
while(q--){
Rd(op),Rd(a),Rd(b);
if(op==1)A[a]=b;
else {
cnt=0;
REP(i,a,b)tmp[++cnt]=A[i];
sort(tmp+1,tmp+1+cnt);
ans=0;
REP(i,1,cnt-2){
REP(j,i+1,cnt-1){
int k=lower_bound(tmp+j+1,tmp+cnt+1,tmp[j])-tmp;
if(tmp[i]+tmp[j]>tmp[k])chkmax(ans,(ll)tmp[i]+tmp[j]+tmp[k]);
}
}
printf("%lld\n",ans);
}
}
}
}p1;
struct p100{
#define lson L,mid,p<<1
#define rson mid+1,R,p<<1|1
struct node{
int L,R;
int len,l[50];
}tree[N<<2],ans;
node Up(node L,node R){
node res;
res.L=L.L,res.R=R.R;
res.len=min(47,L.len+R.len);
int p1=1,p2=1;
REP(i,1,res.len){
if(p1<=L.len && p2<=R.len) res.l[i]=(L.l[p1]>R.l[p2]?L.l[p1++]:R.l[p2++]);
else if(p1<=L.len)res.l[i]=L.l[p1++];
else res.l[i]=R.l[p2++];
}
return res;
}
void build(int L,int R,int p){
tree[p].L=L,tree[p].R=R;
if(L==R){
tree[p].len=1;
tree[p].l[1]=A[L];
return;
}
int mid=(L+R)>>1;
build(lson),build(rson);
tree[p]=Up(tree[p<<1],tree[p<<1|1]);
}
void update(int p,int x,int v){
if(tree[p].L==tree[p].R){
tree[p].l[1]=v;
return;
}
int mid=(tree[p].L+tree[p].R)>>1;
if(x<=mid)update(p<<1,x,v);
else update(p<<1|1,x,v);
tree[p]=Up(tree[p<<1],tree[p<<1|1]);
}
node query(int L,int R,int p){
if(tree[p].L==L && tree[p].R==R)return tree[p];
int mid=(tree[p].L+tree[p].R)>>1;
if(R<=mid)return query(L,R,p<<1);
else if(L>mid)return query(L,R,p<<1|1);
else return Up(query(lson),query(rson));
}
void solve(){
build(1,n,1);
int op,a,b;
while(q--){
Rd(op),Rd(a),Rd(b);
if(op==1)update(1,a,b);
else {
ans=query(a,b,1);
ll res=0;
REP(i,3,ans.len) if(ans.l[i]+ans.l[i-1]>ans.l[i-2]) chkmax(res,1ll*ans.l[i]+ans.l[i-1]+ans.l[i-2]);
printf("%lld\n",res);
}
}
}
}p2;
int main(){
// freopen("triangle.in","r",stdin);
// freopen("triangle.out","w",stdout);
Rd(n),Rd(q);
REP(i,1,n)Rd(A[i]);
if(n<=100 && q<=100)p1.solve();
else p2.solve();
return 0;
}
T3——cactus(3916)
Description:
給出個點,條邊的僅存在簡單環的圖.求對於每個點,刪掉條邊(即變為一棵樹)後的到其它點的最大值的最小值.
Solution:
- 對於題面一上來就仙人掌的…表示很虛啊..
- 但是切完分,發現暴力+圖本為一棵樹的解法差不多就是正解了吧…
- 只不過這裡存在簡單環.我們先tarjan縮點.這裡我順便就用