EXAM-2018-08-21
阿新 • • 發佈:2018-08-27
得到 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