2019icpc銀川站 復現賽

打了計蒜客上的銀川重現賽,整體感受難度上確實比平時區域賽要低上一些。ios

這裏補一下F題和G題的思路和代碼。c++

  • F題

       作法,玩一下n=10的樣例就出來啦!數據結構

  解釋:顯然a^x的反函數爲logax,咱們先固定外層的求和的a,而後看內層求和的b,b從a開始加到n,注意到對於後半個向上取整的logba,b>=a,因此始終都是1,而對於前半個式子,只有當b通過a^i時才增長,舉個例子就是log22~log23向下取整都爲1,log24~log27向下取整都爲2,log28~log210都爲3.函數

對於n=10的樣例,a=2就能夠這樣玩出來,在玩a=3,同理,b從3~10的過程當中,9和10的時候出來2。優化

而對於4和4之後的值,咱們發現後面求和的值都是n-i+1個1,就是從i到n中有多少個數,這部分咱們就能夠用公式算。咋算呢?ui

Σi(n-i+1),顯然 i 從sqrt(n)+1到n,把這個式子拆開來,就能夠獲得公式,此處注意 12+22+……+n2=n*(n+1)*(2n+1)/6;spa

 

至此,咱們就能夠發現規律了!n最大到1e12,咱們就能夠對前sqrt(n)個數暴力的去算。後面部分的完美地去用公式算。debug

不過比賽的時候,取模寫炸了,致使10幾分鐘就推出來的結論,爆炸搞了2個小時,取模要每步取模,因爲這裏的n自己就很大,每一個數自己都要取模,而更重要的是對於除法,取模意義下要用逆元來算,因此就用到了快速冪來求除法逆元。主要是這裏除法常常炸,虧我對拍debug了半天。code

代碼:blog

 1 #include <bits/stdc++.h>
 2 #define debug(x) cout << #x << ": " << x << endl
 3 using namespace std;
 4 typedef long long ll;
 5 const int MAXN=2e5+7;
 6 const int INF=0x3f3f3f3f;
 7 const int MOD=998244353;
 8 
 9 
10 ll quick(ll x,ll n)  //快速冪 x^n
11 {
12     ll res=1;
13     while(n)
14     {
15         if(n&1) res=(res*x)%MOD;
16         x=(x*x)%MOD;
17         n>>=1;
18     }
19     return res;
20 }
21 
22 ll inv(ll a)   //逆元  費馬小定理,要求 a,mod互素
23 {
24     return quick(a,MOD-2);
25 }
26 
27 ll i2sum(ll i)
28 {
29     return (((i%MOD)*((i+1)%MOD))%MOD*(((2*i)%MOD+1)%MOD))%MOD*inv(6)%MOD;
30 }
31 
32 
33 int main()
34 {
35     ios::sync_with_stdio(false);
36     cin.tie(0);
37     ll n;
38     cin>>n;
39     ll ans=0;
40     ll k=(ll)sqrt(n)+1;
41     //debug(k);
42     for(ll i=2;i<k;++i)
43     {
44         ll t=i;
45         ll q=0;
46         while(t<=n)
47         {
48             q=(q+n-t+1)%MOD;
49             t*=i;
50         }
51         ans=(ans+(q%MOD)*(i%MOD)%MOD)%MOD;
52         //debug(ans);
53     }
54     //debug(ans);
55     ans=(ans+(((((n+1)%MOD)*((n-k+1)%MOD))%MOD*(((k+n)%MOD)*inv(2)%MOD)%MOD)%MOD+i2sum(k-1)-i2sum(n)+MOD)%MOD)%MOD;
56    // debug(ans);
57     //ll t=i2sum(n);
58     //debug(t);
59     cout<<ans<<endl;
60     return 0;
61 }
62 //200 1366404
63 //1000 167464908
64 //10000 36893337
65 //100000 384927495
66 //1000000 960529847
67 //10000000 679483439
68 //100000000 498142384

debug和對拍數據沒刪,也能夠對照一下。

  • G題

g題一開始看題目看傻了,p是啥徹底不知道,後來和隊長討論了一下,結合樣例一看,就對上感受了。

由於操做就是乘2到10之間的一個數,很顯然pm | n 且  不pm+1 | n  的m 就是你已經對p乘的操做,須要對照樣例感受一下。

而後維護四棵 區間加法,維護最大值的線段樹了。

而後對於2~10的數你能夠寫if else ,也能夠像我這樣寫,每次差幾個log級update的操做問題不大。

而後這兩天的數據結構和計算幾何題,告訴我這類題必定要scanf,printf,開優化的cin也不行!!!

而後就沒啦!(cry!

 

  1 #include <bits/stdc++.h>
  2 #define debug(x) cout << #x << ": " << x << endl
  3 #define lson (rt<<1)
  4 #define rson (rt<<1|1)
  5 
  6 using namespace std;
  7 typedef long long ll;
  8 const int MAXN=2e5+7;
  9 const int INF=0x3f3f3f3f;
 10 const int MOD=1e9+7;
 11 int prime[4]={2,3,5,7};
 12 
 13 struct tree
 14 {
 15     int seg[MAXN<<2];
 16     int lazy[MAXN<<2];
 17     inline void pushup(int rt){ seg[rt]=max(seg[lson],seg[rson]); }
 18     inline void pushdown(int rt)
 19     {
 20         if(lazy[rt])
 21         {
 22             lazy[lson]+=lazy[rt];
 23             lazy[rson]+=lazy[rt];
 24             seg[lson]+=lazy[rt];
 25             seg[rson]+=lazy[rt];
 26             lazy[rt]=0;
 27         }
 28     }
 29     void build(int l,int r,int rt)
 30     {
 31         seg[rt]=lazy[rt]=0;
 32         if(l==r) {seg[rt]=0;return;}
 33         int m=(l+r)>>1;
 34         build(l,m,lson);
 35         build(m+1,r,rson);
 36         pushup(rt);
 37     }
 38 
 39     void update(int l,int r,int rt,int ql,int qr,ll x)
 40     {
 41         if(ql<=l && r<=qr) {seg[rt]+=x;lazy[rt]+=x;return;}
 42         pushdown(rt);
 43         int m=(l+r)>>1;
 44         if(ql<=m) update(l,m,lson,ql,qr,x);
 45         if(qr>m) update(m+1,r,rson,ql,qr,x);
 46         pushup(rt);
 47     }
 48 
 49     int query(int l,int r,int rt,int ql,int qr)
 50     {
 51         if(ql<=l && r<=qr) return seg[rt];
 52         pushdown(rt);
 53         int m=(l+r)>>1;
 54         int ans=-INF;
 55         if(ql<=m) ans=max(ans,query(l,m,lson,ql,qr));
 56         if(qr>m) ans=max(ans,query(m+1,r,rson,ql,qr));
 57         return ans;
 58     }
 59 }t[4];
 60 
 61 int main()
 62 {
 63     int n,q;
 64     scanf("%d%d",&n,&q);
 65     //for(int i=0;i<4;++i) t[i].build(1,n,1);
 66     while(q--)
 67     {
 68         char s[10];
 69         scanf("%s",s);
 70         int a,b,x;
 71         if(s[1]=='U')
 72         {
 73             scanf("%d%d%d",&a,&b,&x);
 74             for(int i=0;i<4;++i)
 75             {
 76                 int tt=0;
 77                 while(x%prime[i]==0)
 78                 {
 79                     x/=prime[i];
 80                     tt++;
 81                 }
 82                 //debug(tt);
 83                 if(tt!=0) t[i].update(1,n,1,a,b,tt);
 84                 if(x==1) break;
 85             }
 86         }
 87         else
 88         {
 89             scanf("%d%d",&a,&b);
 90             int ans[4];
 91             for(int i=0;i<4;++i)
 92             {
 93                 ans[i]=t[i].query(1,n,1,a,b);
 94                 //debug(ans[i]);
 95             }
 96             int a1=max(ans[0],ans[1]),a2=max(ans[2],ans[3]);
 97             printf("ANSWER %d\n",max(a1,a2));
 98         }
 99     }
100     return 0;
101 }
相關文章
相關標籤/搜索