由于数据很小,直接模拟,注意每个数字必须严格小于进制数
#include
#define rep(i,n) for (int i = 0 ; i < (n) ; ++i)
#define repn(i,n) for (int i = 1; i <= (n) ; ++i)
#define rep2(i,j,n) for (int i = (j) ; i < (n) ; ++i)
#define repn2(i,j,n) for (int i = (j); i <= (n) ; ++i)
#define debug(x) printf("%s = %d\n",#x,x)
#define pb push_back
#define mk make_pair
#define fi first
#define se second
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll mod = 1e9 + 7;
ll qpow(ll a , ll exp ,ll mod = mod){ ll res = 1; while(exp){ if(exp & 1) res = res * a % mod; a = a * a % mod; exp >>= 1;} return res; }
ll inv(ll num , ll mod = mod){ return qpow(num,mod-2);}
#define int ll
struct Moder{
template<typename T> static T add(const T & a ,const T& b){ return ((a+b) % mod + mod) % mod;}
template<typename T> static T mul(const T & a ,const T& b){ return ((a-b) % mod + mod) % mod;}
template<typename T> static T get(const T & a){ return (a % mod + mod) % mod;}
};
struct FIO{ // char*s, int
int c,f,e; operator int() { return ~e; }
FIO& operator >> (char* s){e=scanf("%s",s);return *this;}
template<class T>FIO& operator >> (T& x){
for(f=0;~c&&(c<48||c>57);c=getchar()){if(c=='-')f=1;}
for(x=0,e=c;c>47 && c<58;c=getchar()){x=x*10+(c^48);}
if(f) {x=-x;} return *this;}
};
string s[3];
ll num[3];
int op;
int isOper(char c){
if(c == '+') return 1;
if(c == '-') return 2;
if(c == '*') return 3;
if(c == '/') return 4;
return 0;
}
void split(string str){
int p = 0 , i = 0;
int siz = str.size();
rep(i,3) s[i] = "";
while(! (op = isOper(str[i])) ) {
s[p] = s[p] + str[i];
i++;
}
i++; p++;
while(str[i] != '='){
s[p] = s[p] + str[i];
i++;
} i++; p++;
while(i < siz){
s[p] = s[p] + str[i];
i++;
}
}
int getnum(char c){
if(isdigit(c)) return c-'0';
else return c - 'A' + 10;
}
bool getNum(int id , ll bs){
int len = s[id].size();
ll & tmp = num[id];
tmp = 0;
rep(i,len){
int digit = getnum(s[id][i]);
if(digit >= bs) return 0;
tmp = tmp * bs + digit;
}
return true;
}
bool test(ll bs){
rep(i,3) if(!getNum(i,bs)) return false;
if(op == 1){
return num[0] + num[1] == num[2];
} else if (op == 2){
return num[0] - num[1] == num[2];
} else if (op == 3){
return num[0] * num[1] == num[2];
} else {
return (num[0] / num[1] == num[2]) && (num[0] % num[1] == 0);
}
}
string ss;
signed main()
{
while(cin >> ss){
split(ss);
int res = -1;
for (int i = 2 ; i <= 16 ; ++i){
if(test(i)){
res = i;
break;
}
}
cout << res << endl;
}
return 0;
}
题目大意:
比如能被3整除的数在10进制下有个特点:和能被3整除
给定一个进制和数字,判断是否也有这样类似的性质。
S = a 0 + 10 a 1 + 100 a 2 + . . . . . . . . . 1 0 n a n S = a_0+10a_1+100a_2+.........10^na_n S=a0+10a1+100a2+.........10nan
10进制下为什么会有这个性质呢?
我们让S mod 3 得到如下
S m o d 3 = a 0 + a 1 + a 2 + . . . . . . . . a n S \mod 3 = a_0 + a_1 + a_2 + ........a_n Smod3=a0+a1+a2+........an
可以看出之所以会有这个性质,是因为10的任意次方,对3取余的结果都是1,正因如此,整个式子能被3整除即代表了各个位置和能被3整除
也就是说 ( B a s e − 1 ) m o d X = 0 (Base-1) \mod X = 0 (Base−1)modX=0 成立
#include
#define rep(i,n) for (int i = 0 ; i < (n) ; ++i)
#define repn(i,n) for (int i = 1; i <= (n) ; ++i)
#define rep2(i,j,n) for (int i = (j) ; i < (n) ; ++i)
#define repn2(i,j,n) for (int i = (j); i <= (n) ; ++i)
#define debug(x) printf("%s = %d\n",#x,x)
#define pb push_back
#define mk make_pair
#define fi first
#define se second
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll mod = 1e9 + 7;
ll qpow(ll a , ll exp ,ll mod = mod){ ll res = 1; while(exp){ if(exp & 1) res = res * a % mod; a = a * a % mod; exp >>= 1;} return res; }
ll inv(ll num , ll mod = mod){ return qpow(num,mod-2);}
struct Moder{
template<typename T> static T add(const T & a ,const T& b){ return ((a+b) % mod + mod) % mod;}
template<typename T> static T mul(const T & a ,const T& b){ return ((a-b) % mod + mod) % mod;}
template<typename T> static T get(const T & a){ return (a % mod + mod) % mod;}
};
struct FIO{ // char*s, int
int c,f,e; operator int() { return ~e; }
FIO& operator >> (char* s){e=scanf("%s",s);return *this;}
template<class T>FIO& operator >> (T& x){
for(f=0;~c&&(c<48||c>57);c=getchar()){if(c=='-')f=1;}
for(x=0,e=c;c>47 && c<58;c=getchar()){x=x*10+(c^48);}
if(f) {x=-x;} return *this;}
};
int Case;
ll b,x;
int main()
{
scanf("%d",&Case);
while(Case--){
scanf("%lld%lld",&b,&x);
if((b-1) % x == 0)puts("T");
else puts("F");
}
return 0;
}
题目大意:
给出一张无向图,给出所有顶点的权值V { 0 , 1 } \{0,1\} {0,1}
求所有任意 V a ⊕ V b = 1 V_a \oplus V_b = 1 Va⊕Vb=1 的两点,最短路径和(值计算一次)
V ≤ 1 e 5 , E ≤ 2 e 5 V \leq 1e5 ,E\leq2e5 V≤1e5,E≤2e5
如果题只读到这是根本做不下去的,我一开始忽略了很重要的一句话
第i条边的长度为: 2 i 2^i 2i
也就是说:即便你用尽 1...... ( i − 1 ) 1......(i-1) 1......(i−1)所有的边,都不可能超过第 i i i条长度
于是考虑用并查集维护图的连通性,如果图已经联通,就不考虑后面加入的边(因为肯定不会用这条边),这样一来,我们可以保证最后我们的图只有n-1边,从无向图变成了一颗数。
有道“点分治”模板题是求书上所有点对距离,可以稍作修改
每次分治,分别处理每颗子树,记录序号为0和1的总长度,和记号为0,1的所有点的个数
//sc0: 记录所有子树,权值为0节点总和,在一颗子树搜索完后更新,因为
//点分每一步是考虑跨过根节点的,所以用临时变量存同一颗子树的信息,结束后更新
void dfs(int x, ll cost , int f=-1){
cost %= mod;
if(arr[x] == 0){
c0 += cost; //c0表示权值为0子树结点长度总和
o0++; //o0用于计数
if(cnt1) ans += sc1 + cnt1*cost;
}
else {
c1 += cost;
o1++;
if(cnt0) ans += sc0 + cnt0*cost;
}
ans %= mod;
for (Edge& e : G[x]){
int v = e.v;
if(vis[v] || v == f) continue;
dfs(v,e.cost+cost,x);
}
}
详细处理代码如下
#include
#define rep(i,n) for (int i = 0 ; i < (n) ; ++i)
#define repn(i,n) for (int i = 1; i <= (n) ; ++i)
#define rep2(i,j,n) for (int i = (j) ; i < (n) ; ++i)
#define repn2(i,j,n) for (int i = (j); i <= (n) ; ++i)
#define debug(x) printf("%s = %d\n",#x,x)
#define pb push_back
#define mk make_pair
#define fi first
#define eb emplace_back
#define se second
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll mod = 1e9 + 7;
ll qpow(ll a , ll exp ,ll mod = mod){ ll res = 1; while(exp){ if(exp & 1) res = res * a % mod; a = a * a % mod; exp >>= 1;} return res; }
ll inv(ll num , ll mod = mod){ return qpow(num,mod-2);}
#define int ll
struct Moder{
template<typename T> static T add(const T & a ,const T& b){ return ((a+b) % mod + mod) % mod;}
template<typename T> static T mul(const T & a ,const T& b){ return ((a-b) % mod + mod) % mod;}
template<typename T> static T get(const T & a){ return (a % mod + mod) % mod;}
};
struct FIO{ // char*s, int
int c,f,e; operator int() { return ~e; }
FIO& operator >> (char* s){e=scanf("%s",s);return *this;}
template<class T>FIO& operator >> (T& x){
for(f=0;~c&&(c<48||c>57);c=getchar()){if(c=='-')f=1;}
for(x=0,e=c;c>47 && c<58;c=getchar()){x=x*10+(c^48);}
if(f) {x=-x;} return *this;}
};
const int maxn = 4e5 + 100;
int Case;
int Size;
int n,m,x,y;
int arr[maxn];
int MX;
struct Edge{
int v;
ll cost;
};
vector<Edge> G[maxn];
int siz[maxn], mxson[maxn] , root ,ans;
bool vis[maxn];
int fa[maxn];
void init(const int n){
rep(i,n+2) fa[i] = i;
rep(i,n+2) siz[i] = mxson[i] = vis[i] = 0;
repn(i,n) G[i].clear();
root = ans = 0;
}
int Find(int x){ return fa[x] == x ? x : fa[x] = Find(fa[x]);}
void getroot(int u,int f = -1){
siz[u] = 1; mxson[u] = 0;
for (Edge & e : G[u]){
int v = e.v;
if(f == v || vis[v]) continue;
getroot(v,u);
siz[u] += siz[v];
mxson[u] = max(siz[v],mxson[u]);
}
mxson[u] = max(mxson[u],Size-siz[u]);
if(mxson[u] < MX){
root = u;
MX = mxson[u];
}
}
ll cnt0,cnt1;
ll sc0, sc1;
ll c0,c1;
ll o0,o1;
void dfs(int x, ll cost , int f=-1){
cost %= mod;
if(arr[x] == 0){
c0 += cost;
o0++;
if(cnt1) ans += sc1 + cnt1*cost;
}
else {
c1 += cost;
o1++;
if(cnt0) ans += sc0 + cnt0*cost;
}
ans %= mod;
for (Edge& e : G[x]){
int v = e.v;
if(vis[v] || v == f) continue;
dfs(v,e.cost+cost,x);
}
}
void Divide(int rt , int ssize){
sc0 = 0 , sc1 = 0;
cnt0 = cnt1 = 0;
vis[rt] = 1;
for (Edge& e : G[rt]){
int v = e.v;
if(vis[v]) continue;
c0 = c1 = o0 = o1 = 0;
dfs(v,e.cost,rt);
sc0 += c0; sc1 += c1;
sc0 %= mod; sc1 %= mod;
cnt0 += o0; cnt1 += o1;
}
if(arr[rt] == 0) ans += sc1;
else ans += sc0;
ans %= mod;
for (Edge& e : G[rt]){
int v = e.v;
if(vis[v]) continue;
Size = siz[v];
MX = inf; getroot(v,0);
Divide(root,Size);
}
}
signed main()
{
scanf("%lld",&Case);
while(Case--){
scanf("%lld%lld",&n,&m);
init(n);
ll len = 1;
ans = 0;
repn(i,n) scanf("%lld",arr+i);
Size = n;
repn(i,m){
scanf("%lld%lld",&x,&y);
len <<= 1;
len %= mod;
int fx = Find(x), fy = Find(y);
if(fx == fy) continue;
else fa[fx] = fy;
G[x].eb(Edge{y,len});
G[y].eb(Edge{x,len});
}
root = 0;MX = inf; getroot(1,-1);
Divide(root,n);
cout << ans << endl;
}
return 0;
}
题目大意:任取 i , j , 1 ≤ i ≤ j ≤ n i,j,1\leq i\leq j\leq n i,j,1≤i≤j≤n,求 ∑ k = i j a k / ( j − i + 1 ) \sum_{k=i}^{j}a_k/(j-i+1) ∑k=ijak/(j−i+1)的数学期望
做题时找灵感想到了滑动窗口,比如一个长度为7的数组,
枚举窗口长度和每个数字出现的额次数
l e n = 1 len=1 len=1
1 1 1 1 1 1 1 1 \quad 1 \quad 1 \quad1 \quad1 \quad1 \quad1 \quad 1111111
l e n = 2 len=2 len=2
1 2 2 2 2 2 1 1 \quad 2 \quad 2 \quad2 \quad2 \quad2 \quad1 \quad 1222221
l e n = 3 len=3 len=3
1 2 3 3 3 2 1 1 \quad 2 \quad 3 \quad3 \quad3 \quad2 \quad1 \quad 1233321
l e n = 4 len=4 len=4
1 2 3 4 3 2 1 1 \quad 2 \quad 3 \quad4 \quad3 \quad2 \quad1 \quad 1234321
l e n = 5 len=5 len=5
1 2 3 3 3 2 1 1 \quad 2 \quad 3 \quad3 \quad3 \quad2 \quad1 \quad 1233321
l e n = 6 len=6 len=6
1 2 2 2 2 2 1 1 \quad 2 \quad 2 \quad2 \quad2 \quad2 \quad1 \quad 1222221
l e n = 7 len=7 len=7
1 1 1 1 1 1 1 1 \quad 1 \quad 1 \quad1 \quad1 \quad1 \quad1 \quad 1111111
每次起加点往左一格,结束点往右一格,超过一半后反过来,这就很好做了。
const int maxn = 1e6 + 100;
int Case , n;
ll sum[maxn];
signed main()
{
scanf("%lld",&Case);
while(Case--){
scanf("%lld",&n);
repn(i,n) scanf("%lld",sum+i);
repn(i,n) sum[i] += sum[i-1];
ll d = n*(n+1) / 2; d %= mod;
d = inv(d) % mod;
ll res = 0 , add = 0, div_inv = 0;
int bd = (n+1) / 2;
for (int i = 1 ; i <= bd ; ++i){
add += sum[n-i+1] - sum[i-1];
add %= mod;
div_inv = inv(i);
res += add * div_inv % mod;
res %= mod;
}
add = 0;
for (int i = 1 ; i <= n - bd ; ++i){
add += sum[n-i+1] - sum[i-1];
add %= mod;
div_inv = inv(n-i+1);
res += add * div_inv % mod;
res %= mod;
}
res = res * d % mod;
cout << res << endl;
}
return 0;
}
题目大意: 定义生成树的权值为边权的“与和“。
给点边和点,随机生成一个生成树,求生成树权值的期望。
首先我们要确定一件事情:
“与和“的期望 等于 每一位”与“的期望之和
因此考虑贪心方法:建图,每次只考虑第 i i i位是1的边,进行计算当前生成树数量,这样我们就可以得到:
E ( G ) = ∑ i = 1 n 2 i ∗ C o u n t ( { e d g e ∣ e d g e . c & 2 i = = 1 } ) / C o u n t ( { e d g e } ) E(G) = \sum_{i=1}^{n}2^i*Count(\{edge | edge.c \&2^i == 1\}) / Count(\{edge\}) E(G)=∑i=1n2i∗Count({edge∣edge.c&2i==1})/Count({edge})
问题就在于如何求生成树个数了
有个 M a t r i x − t r e e Matrix-tree Matrix−tree定理,就是关于这个的,这个我也是只知道,只会拿来用,详情可以看看别人的博客
#include
#define rep(i,n) for (int i = 0 ; i < (n) ; ++i)
#define repn(i,n) for (int i = 1; i <= (n) ; ++i)
#define rep2(i,j,n) for (int i = (j) ; i < (n) ; ++i)
#define repn2(i,j,n) for (int i = (j); i <= (n) ; ++i)
#define debug(x) printf("%s = %d\n",#x,x)
#define pb push_back
#define mk make_pair
#define fi first
#define eb emplace_back
#define se second
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll mod = 998244353;
#define int ll
ll qpow(ll a , ll exp ,ll mod = mod){ ll res = 1; while(exp){ if(exp & 1) res = res * a % mod; a = a * a % mod; exp >>= 1;} return res; }
ll inv(ll num , ll mod = mod){ return qpow(num,mod-2);}
struct Moder{
template<typename T> static T add(const T & a ,const T& b){ return ((a+b) % mod + mod) % mod;}
template<typename T> static T mul(const T & a ,const T& b){ return ((a-b) % mod + mod) % mod;}
template<typename T> static T get(const T & a){ return (a % mod + mod) % mod;}
};
struct FIO{ // char*s, int
int c,f,e; operator int() { return ~e; }
FIO& operator >> (char* s){e=scanf("%s",s);return *this;}
template<class T>FIO& operator >> (T& x){
for(f=0;~c&&(c<48||c>57);c=getchar()){if(c=='-')f=1;}
for(x=0,e=c;c>47 && c<58;c=getchar()){x=x*10+(c^48);}
if(f) {x=-x;} return *this;}
};
const int maxn = 2e4+ 100;;
#define LL ll
int Case;
//图论部分
struct Edge{
int u,v;
ll cost;
};
const int N = 111;
LL K[N][N];
LL gauss(int n){
LL res=1;
for(int i=1;i<=n-1;i++){
for(int j=i+1;j<=n-1;j++){
while(K[j][i]){
int t=K[i][i]/K[j][i];
for(int k=i;k<=n-1;k++)
K[i][k]=(K[i][k]-t*K[j][k]+mod)%mod;
swap(K[i],K[j]);
res=-res;
}
}
res=(res*K[i][i])%mod;
}
return (res + mod) % mod;
}
int n,m;
vector<Edge> edge;
void build(int x){
memset(K,0,sizeof(K));
for(Edge&e : edge){
int u = e.u , v = e.v;
ll c = e.cost;
if((c>>x) & 1){
K[u][u]++; K[v][v]++;
K[u][v]--; K[v][u]--;
}
}
}
signed main()
{
scanf("%lld",&Case);
while(Case--){
edge.clear();
memset(K,0,sizeof(K));
ll total = 0;
int x,y,z;
scanf("%lld%lld",&n,&m);
repn(i,m){
scanf("%lld%lld%lld",&x,&y,&z);
edge.eb(Edge{x,y,z});
K[x][x]++; K[y][y]++;
K[x][y]--; K[y][x]--;
}
total = gauss(n);
ll inv_t = inv(total);
ll res = 0;
for (int i = 30 ; i >= 0 ; --i){
ll base = 1LL << i;
build(i);
ll cnt = gauss(n);
ll tmp = base * cnt % mod * inv_t % mod;
res = (res + tmp) % mod;
}
cout << res << endl;
}
return 0;
}
题目大意:(太 臭 了)
一个无限序列114514919114514…
可以用 + , ∗ + , * +,∗和括号来连接,给出t个询问,
问想要获得数 N ≤ 5000 N\leq 5000 N≤5000,至少需要多长的序列(序列从头开始)
做法:…暴力跑了dp10位后…发现3,7不行,其余都行。。。。直接交了
(做法太臭了)
#include
#define rep(i,n) for (int i = 0 ; i < (n) ; ++i)
#define repn(i,n) for (int i = 1; i <= (n) ; ++i)
#define rep2(i,j,n) for (int i = (j) ; i < (n) ; ++i)
#define repn2(i,j,n) for (int i = (j); i <= (n) ; ++i)
#define debug(x) printf("%s = %d\n",#x,x)
#define pb push_back
#define mk make_pair
#define fi first
#define se second
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll mod = 1e9 + 7;
ll qpow(ll a , ll exp ,ll mod = mod){ ll res = 1; while(exp){ if(exp & 1) res = res * a % mod; a = a * a % mod; exp >>= 1;} return res; }
ll inv(ll num , ll mod = mod){ return qpow(num,mod-2);}
struct Moder{
template<typename T> static T add(const T & a ,const T& b){ return ((a+b) % mod + mod) % mod;}
template<typename T> static T mul(const T & a ,const T& b){ return ((a-b) % mod + mod) % mod;}
template<typename T> static T get(const T & a){ return (a % mod + mod) % mod;}
};
struct FIO{ // char*s, int
int c,f,e; operator int() { return ~e; }
FIO& operator >> (char* s){e=scanf("%s",s);return *this;}
template<class T>FIO& operator >> (T& x){
for(f=0;~c&&(c<48||c>57);c=getchar()){if(c=='-')f=1;}
for(x=0,e=c;c>47 && c<58;c=getchar()){x=x*10+(c^48);}
if(f) {x=-x;} return *this;}
};
const int maxn =155;
const int bb = 5000;
set<int> F[maxn][maxn];
bool vis[maxn][maxn];
int arr[10] = {1,1,4,5,1,4,1,9,1,9};
int con(int a , int b){
int t = 10;
int tb = 0;
while(tb){
t *= 10;
tb /= 10;
}
return a * t + b;
}
set<int> & dp (int l , int r){
if(vis[l][r]) return F[l][r];
vis[l][r] = 1;
set<int> & tmp = F[l][r];
if(l == r){
int digit = arr[l%10];
tmp.insert(digit);
return tmp;
}
int p = l;
int sum = 0;
while(p <= r){
sum = sum * 10 + arr[p % 10];
if(sum > 5000) break;
p++;
}
if(sum <= 5000) tmp.insert(sum);
for(int i = l ; i < r ; ++i){
set<int> &left = dp(l,i);
set<int> &right = dp(i+1,r);
if(l == 0 && r == 5 && i == 2){
int p = 1;
p++;
}
for (int lv : left) for (int rv : right){
if(lv * rv <= 5000){
tmp.insert(lv * rv);
}
if(lv + rv <= 5000){
tmp.insert(lv + rv);
}
}
}
return tmp;
}
map<int,int> mps;
int main()
{
int Case;
FIO read;
dp(0,10);
int p = 0;
for (int i = 0 ; i <= 10 ; ++i)
for (int v : F[0][i]) {
if(mps[v] == 0) {
//cout << v << ' ';
mps[v] = i + 1;
}
}
mps[0] = 0;
scanf("%d",&Case);
while(Case--){
int p ;
cin >> p;
if(mps.find(p) == mps.end()) puts("-1");
else cout << mps[p] << endl;
}
return 0;
}