2018.7.20日記&總結

今天又只過了一題,很差!!!
E題應該能想出來的,構造題多找性質,發現很強的性質後構造就很方面了。
看題要有舍有得,有些題顯然很難就沒必要看了。把注意力放在有人做的可做題上,靜下心來深入思考很重要。
如果沒有別的題可做,1道題想一小時很正常。多想別的做法,甚至亂搞,但是肯定不能過的做法別多糾結。膽大嘗試做法,但過不了果斷放棄,不要浪費太多時間。
大膽利用性質猜結論!
調題應該更快,敢於問。注意細節錯誤!靜下心來用眼讀代碼,邊讀邊思考,減少對拍,因爲考場上沒法也沒時間對拍!!!

題解:
A:求多項式的商。巧妙推式子。
主要是推式子很巧,很好寫!

#include<bits/stdc++.h>
using namespace std;
#define maxn 5020
#define rep(i,l,r) for(register int i = l ; i <= r ; i++)

typedef long long ll;
const ll mod = 1e9 + 7;
ll a[maxn],b[maxn],c[maxn],ans,mx;
int m;

inline ll power(ll x,ll y){
    ll res = 1;
    while ( y ){
        if ( y & 1 ) res = res * x % mod;
        x = x * x % mod;
        y >>= 1;
    }
    return (res + mod) % mod;
}
void cal_C(){
    rep(i,1,m){
        ll mul = 1,x = 1,cur = 0;
        rep(j,1,m) if ( j != i ) mul = mul * (a[j] - a[i]) % mod;
        mul = power(mul,mod - 2);
        rep(j,0,m - 2) cur = (cur + x * b[j]) % mod , x = x * (-a[i]) % mod;
        c[i] = (cur * mul % mod + mod) % mod;
    }
    //rep(i,1,m) c[i] = (c[i] + c[i - 1]) % mod;
}
void solve(){
    rep(i,1,mx){
        ll cur = 0;
        rep(j,1,m){
            if ( a[j] < i ) cur = (cur + c[j]) % mod;
        }
        ans = (ans + cur * power(i,mod - 2)) % mod;
    }
    ans = (ans % mod + mod) % mod;
    printf("%lld\n",ans);
}
int main(){
    freopen("input.txt","r",stdin);
    while ( ~scanf("%d",&m) ){
        mx = ans = 0;
        rep(i,1,m) scanf("%lld",&a[i]) , mx = max(mx,a[i]);
        rep(i,0,m - 2) scanf("%lld",&b[i]);
        cal_C();
        solve();
    }
    return 0;
}

B:巧妙的貪心,利用每個聯通塊必選一個點,其餘點從小到大選。大膽推性質,想結論!

C:N*N矩陣,每行每列填一個數,使兩兩連線不同。
用原根構造(g^(1 - n-1)恰好爲1- p-1).因爲保證n +1爲質數,所以大膽猜想與原根有關。
填(i,g^i % (n + 1))

D:求對於每個前綴i,找一個分界點j,xorsum(1,j) + xorsum(j +1,i)最大。
每一位,出現奇數次爲0(因爲無論怎麼選都貢獻1),偶數次爲1(想選到奇數次分開,就貢獻2)
相當於查詢x在pre中&的最大值。
F[1<<10][1<<10]的分塊過不了
考慮直接對一個pre的所有子集進行更新,查詢時只需知道當前要填的數是否被包含,就可以唯一確定,非常巧妙!
O(nlogn)
注意輸出優化要特判負數和0

#pragma GCC optimize(3)
#include<bits/stdc++.h>
using namespace std;
#define maxn (1 << 22)
#define rep(i,l,r) for(register int i = l ; i <= r ; i++)
#define repd(i,r,l) for(register int i = r ; i >= l ; i--)
#define inf 1e8

int a[maxn],ans[maxn],n;
int q[maxn],hh,tt,dfstime,vis[maxn];


inline int read(){
    register int num = 0;
    register char ch = getchar();
    while ( ch > '9' || ch < '0' ) ch = getchar();
    while ( ch <= '9' && ch >= '0' ) num = num * 10 + ch - '0' , ch = getchar();
    return num;
}
int num[10];
inline void write(int x){
    register int cnt = 0;
    if ( !x ){ printf("0"); return; }
    while ( x ) num[++cnt] = x % 10 , x /= 10;
    while ( cnt ) putchar(num[cnt--] + '0');
}
inline void insert(int x){
    if ( vis[x] == dfstime ) return;
    tt = hh = 0; q[tt++] = x , vis[x] = dfstime;
    while ( hh < tt ){
        int x = q[hh++];
        if ( !x ) continue;
        rep(i,0,19){
            if ( (x >> i) & 1 ){
                if ( vis[x ^ (1 << i)] != dfstime ){
                    vis[x ^ (1 << i)] = dfstime;
                    q[tt++] = x ^ (1 << i);
                }
            }
        }
    }
}
inline int query(int x){
    int cur = 0;
    repd(i,19,0){
        if ( x & (1 << i) ){
            if ( vis[cur | (1 << i)] == dfstime ) cur |= 1 << i;
        }
    }
    return cur;
}
int main(){
    freopen("input.txt","r",stdin);
//  freopen("1.out","w",stdout);
    while ( ~scanf("%d",&n) ){
        ++dfstime;
        int pre = 0,cur = 0,S = (1 << 20) - 1;
        rep(i,1,n){
            a[i] = read() , pre ^= a[i] , cur = pre ^ S;
            insert(pre);
            ans[i] = query(cur) * 2 + pre;
        }
        rep(i,1,n){
            write(ans[i]);
        //  if ( i < n ) putchar(' ');  
        //  else putchar(10);
            if ( i < n ) printf(" ");
            else printf("\n");
        }
    }
    return 0;
}

E:給出後綴排序後第i位的位置,構造一個0,1的可行解。
每次找到最後一個位置的排名,如果在第一則填0刪去,不影響其他點排名。如果不在第一位則必須填1。並且它之前全部爲0,之後全部爲1。再一次後綴數組判斷是否可行。
注意後綴數組有些地方要倒着for(位置靠後字典序更小)
還要一種很巧的判定方法。
rk[sa[i] +1] > rk[sa[i +1] +1]則所需字符集+1,使用於字符集更大的情況

#include<bits/stdc++.h>
using namespace std;
#define maxn 100020
#define rep(i,l,r) for (register int i = l ; i <= r ; i++)
#define repd(i,r,l) for(register int i = r ; i >= l ; i--)

int a[maxn];
int s[maxn],c[maxn],t1[maxn * 2],t2[maxn * 2],sa[maxn];
int n;


//sa[i]表示排名爲i的後綴的位置
    //rk[i]表示第i個後綴的排名
    //x[i]表示i的排名(第一關鍵字)
    //y[i]表示第二關鍵字排名爲i的後綴的起始位置
    //h[i]表示後綴i在排序後與前一位的lcp
    //求i,j的lcp是排序後rk[i],rk[j],height的min

void suffix_array(){
    int m = 1 , *x = t1 , *y = t2;
    rep(i,0,m) c[i] = 0;
    rep(i,0,n - 1) c[x[i] = s[i]]++;
    rep(i,1,m) c[i] += c[i - 1];
    rep(i,0,n - 1) sa[--c[x[i]]] = i;
//  rep(i,1,n) cout<<sa[i - 1]<<" ";
//  cout<<endl;;    
    for (register int k = 1 ; k < n ; k <<= 1){
        register int p = 0;
        memset(y,0,sizeof(t1));
        repd(i,n - 1,n - k) y[p++] = i; //必須倒着for,在後面的位置更小
        rep(i,0,n - 1) if ( sa[i] >= k ) y[p++] = sa[i] - k;

        rep(i,0,m) c[i] = 0;
        rep(i,0,n - 1) c[x[y[i]]]++;
        rep(i,1,m) c[i] += c[i - 1];
        repd(i,n - 1,0) sa[--c[x[y[i]]]] = y[i];

        p = 0 , swap(x,y) , x[sa[0]] = ++p;
        rep(i,1,n - 1) x[sa[i]] = (y[sa[i]] == y[sa[i - 1]]) && (y[sa[i] + k] == y[sa[i - 1] + k]) ? p : ++p;
        if ( p >= n ) break; //如果當前已經完成排名,則break
        m = p;
    }
}

bool check(){
//  rep(i,1,n) cout<<sa[i - 1]<<" ";
//  cout<<endl;;
    rep(i,1,n) if ( a[i] != sa[i - 1] + 1 ) return 0;
    return 1;
}
int main(){
    freopen("input.txt","r",stdin);
    while ( ~scanf("%d",&n) ){
        rep(i,1,n) scanf("%d",&a[i]);
        int id = 1;
        while ( a[id] == n - id + 1 ) id++;
        if ( id >= n ){ printf("YES\n"); continue; }
        rep(i,id,n) if ( a[i] == n - id + 1){ id = i; break; }
        rep(i,1,id - 1) s[a[i] - 1] = 0;
        rep(i,id,n) s[a[i] - 1] = 1;
        suffix_array();
        if ( check() ) printf("YES\n");
        else printf("NO\n");        
    }
    return 0;
}

F:特技分塊,好題

#pragma GCC optimize(3)
#include<bits/stdc++.h>
using namespace std;
#define maxn 200020
#define rep(i,l,r) for(register int i = l ; i <= r ; i++)
#define repd(i,r,l) for(register int i = r ; i >= l ; i--)
#define inf 1e8

typedef long long ll;
inline int read(){
    register int num = 0;
    register char ch = getchar();
    while ( ch > '9' || ch < '0' ) ch = getchar();
    while ( ch <= '9' && ch >= '0' ) num = num * 10 + ch - '0' , ch = getchar();
    return num;
}
int num[10];
inline void write(int x){
    register int cnt = 0;
    if ( !x ){ printf("0"); return; } //Ò»¶šÒªÌØÅÐ0£¡£¡£¡
    while ( x ) num[++cnt] = x % 10 , x /= 10;
    while ( cnt ) putchar(num[cnt--] + '0');
}
struct node{
    int x,y;
}dt[maxn];
int n,m,q,deg[maxn],sz,tag[maxn],id[maxn],tot,exi[maxn];
ll v[maxn],w[2][1020][1020];
int big[maxn],rev[maxn];
vector <int> vec[maxn];

void init(){
    rep(i,1,n) tag[i] = deg[i] = id[i] = 0 , vec[i].clear();
    rep(i,1,n) v[i] = (ll)rand() * rand() * rand();
    rep(i,0,m / sz) rev[i] = 0;
    rep(i,0,m) exi[i] = 1;
    memset(w,0,sizeof(w));
    tot = 0;
}

inline void update(int i,int cur){
    int x = dt[i].x , y = dt[i].y;
    if ( tag[x] ){
        w[0][cur][id[x]] ^= v[y];
        w[1][cur][id[x]] ^= v[y];
    }
    if ( tag[y] ){
        w[0][cur][id[y]] ^= v[x];
        w[1][cur][id[y]] ^= v[x];
    }
}
inline void modify(int l,int r){
    int L = l == 0 ? 0 : ((l - 1) / sz + 1),R = (r + 1) / sz - 1;
    rep(i,L,R){
        rev[i] ^= 1;
    }
    if ( R >= L ){
        rep(i,l,sz * L - 1) exi[i] ^= 1 , update(i,i / sz);
        rep(i,(R + 1) * sz,r) exi[i] ^= 1 , update(i,i / sz);
    }
    else{
        //ÖЌ䲻°üº¬ÈÎÒâÒ»¿éÒªÌØÅÐ
        rep(i,l,r) exi[i] ^= 1 , update(i,i / sz);
    }
}
inline ll cal(int id,int x){
    if ( exi[id] ^ rev[id / sz] ){
        if ( dt[id].x == x ) return v[dt[id].y];
        return v[dt[id].x];
    }
    return 0;
}
ll query(int x){
    ll res = 0;
    if ( tag[x] ){
        rep(i,0,m / sz){
            res ^= w[rev[i]][i][id[x]];
        }
    }
    else{
        for (register int i = 0 ; i < vec[x].size() ; i++){
            res ^= cal(vec[x][i],x);
        }
    }
    return res;
}
int main(){
    freopen("input.txt","r",stdin);
    while ( ~scanf("%d %d",&n,&m) ){
        sz = sqrt(m * 2);
        init();
        rep(i,0,m - 1){
            dt[i].x = read() , dt[i].y = read();
            deg[dt[i].x]++ , deg[dt[i].y]++;
            vec[dt[i].x].push_back((int)i) , vec[dt[i].y].push_back((int)i);
        }
        rep(i,1,n) if ( deg[i] > sz ) tag[i] = 1 , big[++tot] = i , id[i] = tot;;
        rep(i,0,m / sz){
            rep(j,i * sz,min(m - 1,(i + 1) * sz - 1)){
                int x = dt[i].x,y = dt[i].y;
                if ( tag[x] ) w[0][i][id[x]] ^= v[y];
                if ( tag[y] ) w[0][i][id[y]] ^= v[x];
            }
        }
        q = read();
        while ( q-- ){
            int tp,x,y;
            tp = read() , x = read() , y = read();
            if ( tp == 1 ){
                modify(x - 1,y - 1);
            }
            else{
                if ( query(x) == query(y) ) printf("1");
                else printf("0");
            }
        }
        printf("\n");
    }
    return 0;
}

G:NTT優化數位DP

#include<bits/stdc++.h>
using namespace std;
#define maxn 100020
#define rep(i,l,r) for(register int i = l ; i <= r ; i++)
#define repd(i,r,l) for(register int i = r ; i >= l ; i--)
#define inf 1e8

inline int read(){
    register int num = 0;
    register char ch = getchar();
    while ( ch > '9' || ch < '0' ) ch = getchar();
    while ( ch <= '9' && ch >= '0' ) num = num * 10 + ch - '0' , ch = getchar();
    return num;
}
int num[10];
inline void write(int x){
    register int cnt = 0;
    if ( !x ){ printf("0"); return; } //Ò»¶šÒªÌØÅÐ0£¡£¡£¡
    while ( x ) num[++cnt] = x % 10 , x /= 10;
    while ( cnt ) putchar(num[cnt--] + '0');
}

typedef long long ll;
const ll p = 998244353,g = 3;
const int len = 32768,cnt = 15,mod = 10857;
ll f[32][maxn],c[maxn],res[maxn],inv;
int n,rev[maxn];
int a[6] = {2,3,5,7,11,47},t[5] = {1,2,3,5,7};

inline ll power(ll x,ll y,ll p){
    ll res = 1;
    while ( y ){
        if ( y & 1 ) res = res * x % p;
        x = x * x % p;
        y >>= 1;
    }
    return res;
}

void NTT(ll a[],int tag){
    rep(i,0,len - 1) if ( rev[i] > i ) swap(a[rev[i]],a[i]);
    for (register int i = 1 ; i < len ; i <<= 1){
        ll wn = power(g,(p - 1) / (i << 1),p);
        for (register int j = 0 ; j < len ; j += (i << 1)){
            ll w = 1;
            for (register int k = 0 ; k < i ; k++){
                ll x = a[j + k] , y = a[i + j + k] * w % p;
                a[j + k] = (x + y) % p;
                a[i + j + k] = (x - y + p) % p;
                w = w * wn % p;
            }
        }
    }
    if ( tag == -1 ){
        reverse(a + 1,a + len);

        rep(i,0,len - 1) a[i] = inv * a[i] % p;
    }
}
void qpow(ll a[],ll b[],ll n){
    rep(i,0,len - 1) c[i] = 0;
    rep(i,0,len - 1) c[n * i % mod] = (c[n * i % mod] + a[i]) % p;
    NTT(c,1);
    rep(i,0,len - 1) c[i] = c[i] * b[i] % p;
    NTT(c,-1);
    rep(i,0,len - 1) a[i] = 0;
    rep(i,0,len - 1) a[i % mod] = (a[i % mod] + c[i]) % p;
}
void init(){
    inv = power(len,p - 2,p);
    rep(i,0,len - 1){
        int cur = 0;
        rep(j,0,cnt - 1){
            if ( i & (1 << j) ) cur += 1 << (cnt - j - 1);
        }
        rev[i] = cur;
    }
    rep(i,0,4) f[0][t[i]] = 1;
    rep(i,1,29){
        memcpy(f[i],f[i - 1],sizeof(f[i])) , NTT(f[i - 1],1);
        qpow(f[i],f[i - 1],power(10,1 << (i - 1),mod));
    }
    NTT(f[29],1);
}
int check(int x){
    rep(i,0,5) if ( (x % a[i]) == 0 ) return 0;
    return 1;
}
int main(){
//  freopen("input.txt","r",stdin);
    init();
    while ( ~scanf("%d",&n) ){
        n--;
        memset(res,0,sizeof(res));
        res[0] = 1;
        repd(i,29,0){
            if ( n & (1 << i) ) qpow(res,f[i],power(10,1 << i,mod));
        }       
        ll ans = 0;
    //  rep(i,0,10) cout<<res[i]<<" ";
    //  cout<<endl;
        rep(i,0,mod - 1){
            int cnt = 0;
            rep(j,0,4) if ( check(i * 10 + t[j]) ) cnt++;
            ans = (ans + res[i] * cnt) % p;
        }
        printf("%lld\n",ans);
    }
    return 0;
}

H:用圓的包含關係建樹,然後DP,明天寫

明天目標過3題,進入前5名!提高思維速度,減少代碼錯誤和罰時,靜心深入思考!!!
明天早點睡!一刻不能放鬆!先調完題才能回寢室!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章