1. 程式人生 > >EXAM-2018-08-21

EXAM-2018-08-21

得到 max 題解 || != c++ bit getc sum

EXAM-2018-08-21

自己真的是菜的恐怖

D:Fence Building

歐拉公式:V-E+F=2
在平面中:V為頂點個數,E為邊數,F為區域數
在簡單幾何體中:V為頂點個數,E為邊數,F為面數

考慮到區域最多,每個交點最多由兩條線構成。 頂點數為C(n,4);邊數為C(n,2)+2*C(n,4) 然後減去圓外的.

I: A Possible Tree

  • 題意: 給定一棵帶權樹的形態, 但是並不知道每天條邊的具體權重. 然後給m個信息, 信息格式為u v val, 表示在樹上u 到 v 的路徑上經過的邊的權重的異或和為val, 問前面最多有多少個信息是不沖突的.
  • 題解:從沖不沖突應該想到使用並查集,通過那m次信息構建最小生成樹,如果不屬於這個集合的就加入集合,屬於的就判斷是否與之前的最小生成樹矛盾。主要是在這個集合內的兩點,可以很輕松查詢到。(畫圖理解)val[]記錄根節點到該點的距離,然後通過find時路徑壓縮的操作和add操作更新val[]。這道題寫起來很簡單,就是難想到。
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+7;
int fa[maxn],val[maxn];
int n;
template<class T>
void read(T &res){
    res=0;
    T f=1;
    char c=getchar();
    while(c<'0'||c>'9'){
        if(c=='-') f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9'){
        res=res*10+c-'0';
        c=getchar();
    }
    res*=f;
}
void init()
{
    for(int i=0;i<=n;i++) fa[i]=i;
    memset(val,0,sizeof(val));
}
int findd(int u){
    if(u!=fa[u]){
     int v=fa[u];
     fa[u]=findd(v);
     val[u]^=val[v];
    }
    return fa[u];
}
bool add(int u,int v,int w){
    int a=findd(u);
    int b=findd(v);
    if(a!=b){
        val[a]=val[v]^val[u]^w;
        fa[a]=b;
        return true;
    }
    if((val[u]^val[v])!=w) return false;
    else return true;
}
int main(){
    int t;
    read(t);
    int u,v,m,w;
    while(t--){
        read(n);
        read(m);
        init();
        for(int i=1;i<n;i++){
            read(u);
            read(v);
        }
        int flag=0;
        for(int i=1;i<=m;i++){
            read(u);
            read(v);
            read(w);
            if(!add(u,v,w)&&!flag){
                flag=i;
            }
        }
        printf("%d\n",flag-1);
    }
    return 0;
}

H Count Numbers

cur[n]表示數位和為n的方案數,ans[n]表示前n位的答案。 我們發現,比如說4,方案數等於cur[2]+cur[2],cur[3]+cur[1],cur[4]+cur[0]。通過枚舉最後一位就可以得到答案。

cur[i]=SUM cur[i-j];

而和就是前面的位* 10加上與i的差*與i的差的數的方案數。

ans[i]=SUM ans[i-j]*10+j*cur[i-j];

接下來就是矩陣快速冪 枚舉18位 構成18*18的矩陣
然後註意寫法就好。__int128

#include <bits/stdc++.h>
#define ll long long
using namespace std;
template<class T>
void read(T &res){
    res=0;
    T f=1;
    char c=getchar();
    while(c<'0'||c>'9'){
        if(c=='-') f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9'){
        res=res*10+c-'0';
        c=getchar();
    }
    res*=f;
}
struct mac{
    ll f[20][20];
    mac(){
       for(int i=0;i<20;i++){
        for(int j=0;j<20;j++){
            f[i][j]=0;
        }
       }
    }
    void init()
    {
        for(int i=0;i<20;i++){
             
                f[i][i]=1;
        }
    }
};
int p;
mac operator*(mac a,mac b)
{
    mac c;
    for(int i=0;i<18;i++){
        for(int j=0;j<18;j++){
            if(a.f[i][j])
            for(int k=0;k<18;k++){
                if(b.f[j][k]){
                c.f[i][k]=c.f[i][k]+(a.f[i][j]%p*b.f[j][k]%p)%p;
                if(c.f[i][k]>=p) c.f[i][k]-=p;
                }
            }
        }
    }
    return c;
}
mac qpow(mac a,__int128 k)
{
    mac c;
    c.init();
    while(k>0){
        if(k&1) c=c*a;
        a=a*a;
        k>>=1;
    }
    return c;
}
ll ans[18],cur[18];
int main()
{
    int t;int x,y;
    mac a,b;
    read(t);
    cur[0]=1;
    for(int i=1;i<=9;i++){
        for(int j=1;j<=i;j++){
            cur[i]+=cur[i-j];
            ans[i]+=10*ans[i-j]+j*cur[i-j];
        }
    }
    for(int i=0;i<9;i++) a.f[i][0]=10;
    for(int i=9;i<18;i++) a.f[i][0]=i-8;
    for(int i=1;i<9;i++){
        a.f[i-1][i]=1;
    }
    for(int i=10;i<18;i++){
        a.f[i-1][i]=1;
    }
    for(int i=9;i<18;i++){
        a.f[i][9]=1;
    }
//    for(int i=0;i<18;i++){
//        for(int j=0;j<18;j++){
//            cout<<setw(3)<<a.f[i][j];
//        }
//        cout<<endl;
//    }
    while(t--){
        read(x);
        read(y);
        read(p);
        for(int i=0;i<9;i++) b.f[0][i]=ans[9-i]%p;
        for(int j=9;j<18;j++) b.f[0][j]=cur[18-j]%p;
//        for(int i=0;i<18;i++){
//            cout<<b.f[0][i]<<" ";
//        }
        __int128 k=1;
        for(int i=1;i<=y;i++) k*=(__int128)x;
        //cout<<k<<endl;
        if(k<=9){
            printf("%lld\n",ans[k]%p);
        }
        else{
            mac ak=b*qpow(a,k-9);
            printf("%lld\n",ak.f[0][0]);
        }
    }
    return 0;
}
/*5
3 2 100000
*/

EXAM-2018-08-21