A:判断a,b之间是否有倍数关系,没有输出-1。求出a,b之间的倍数cnt,观察该倍数是否为2的幂次,如果不是输出-1。如果2^x == cnt。按照8,4,2的顺序依次把x取完.
#include<bits/stdc++.h> using namespace std; #define N 2010 #define maxn (N + 10) #define maxm (N * 2) typedef long long ll; const ll INF = (1e7); int main(){ int t;scanf("%d",&t); while(t--){ ll a,b;scanf("%lld%lld",&a,&b); ll cnt = 0; int flag = 0; if(a % b == 0){ cnt = a / b;flag = 1; } if(b % a == 0){ cnt = b / a;flag = 1; } int n2 = 0; while(cnt > 1){ if(cnt % 2 != 0){ flag = 0;break; } cnt /= 2;n2++; } ll ans = 0; if(!flag){ ans = -1; } else{ ans += n2 / 3;n2 %= 3; ans += n2 / 2;n2 %= 2; ans += n2; } printf("%lld ",ans); } return 0; }
B:对于每一个si,判断二进制位j是否为1,唯一则bits[j]++。容易发现,除了bits[j] * 2 == n的情况,其他情况答案ans在第j位只能取0。所以记录下所有符合bits[j] * 2 == n的位数。然后dfs找到最小答案。
#include<bits/stdc++.h> using namespace std; #define N 2010 #define maxn (N + 10) #define maxm (N * 2) typedef long long ll; const ll INF = (1e7); int s[maxn]; int vis[maxn]; int bits[40]; int b[maxn],bn; int n,ans; void dfs(int idx,int cnt){ if(!idx){ if(!cnt)return; for(int i = 1;i <= n;i++){ vis[cnt ^ s[i]]--; } int flag = 1; for(int i = 1;i <= n;i++){ if(vis[s[i]] != 0){ flag = 0;break; } } if(flag){ ans = cnt; return; } for(int i = 1;i <= n;i++){ vis[s[i]] = 1; } return; } dfs(idx - 1,cnt); if(ans)return; dfs(idx - 1,cnt | (1<<b[idx])); } int main(){ int t;scanf("%d",&t); while(t--){ memset(bits,0, sizeof(bits)); memset(vis,0, sizeof(vis)); scanf("%d",&n); for(int i = 1;i <= n;i++){ scanf("%d",&s[i]); vis[s[i]]++; for(int j = 0;j <= 10;j++){ if(s[i]&(1<<j)){ bits[j]++; } } } ans = 0; bn = 0; for(int i = 0;i <= 10;i++){ if(bits[i] * 2 == n){ b[++bn] = i; } } dfs(bn,0); if(!ans)ans = -1; printf("%d ",ans); } return 0; }
C:容易发现1-2^x的和为2^(x+1)-1,所以从高位向低位遍历。例如101010010,当遍历到左边第一个1时,求出1 - 100000000的和,当遍历到第二个1时,求出100000001 - 101000000的和,因为前边的位数异或值为零,所以等价于求1 - 1000000的和。所以每一个为1的位数加上相应的前缀和就行。
#include<bits/stdc++.h> using namespace std; #define N 2010 #define maxn (N + 10) #define maxm (N * 2) typedef long long ll; const ll INF = (1e7); int s[maxn]; int vis[maxn]; int bits[40]; int b[maxn],bn; int n,ans; void init(){ ll ans = 0; for(ll i = 1;i <= N;i++){ ll x = (i^(i - 1)); for(int j = 0;j < 32;j++){ if(x & (1<<j))ans++; } printf("i = %lld ans = %lld ",i,ans); } } int main(){ //init(); int t;scanf("%d",&t); while(t--){ ll n;scanf("%lld",&n); ll ans = 0; for(ll i = 61;i >= 0;i--){ if(n & (1ll<<i)){ ans += (1ll<<(i + 1)) - 1; } } printf("%lld ",ans); } return 0; }
D:容易发现,topic小的blog必须先放,每一个blog的能取tp,只有1-(tp-1)它的邻居都有,且它没有话题为tp的邻居。
#include<bits/stdc++.h> using namespace std; #define N 500010 #define maxn (N + 10) #define maxm (N * 2) #define pb push_back typedef long long ll; const ll INF = (1e7); struct blogs{ int tp,id; }b[maxn]; vector<int> vc[maxn]; int oup[maxn],on; int hp[maxn],col[maxn]; bool cmp(blogs x,blogs y){ return x.tp < y.tp; } int main(){ //init(); int n,m;scanf("%d%d",&n,&m); for(int i = 1;i <= m;i++){ int u,v;scanf("%d%d",&u,&v);vc[u].pb(v);vc[v].pb(u); } for(int i = 1;i <= n;i++){ scanf("%d",&b[i].tp);b[i].id = i; } sort(b + 1,b + 1 + n,cmp); on = 0; int flag = 1; for(int i = 1;i <= n;i++){ oup[++on] = b[i].id;int u = b[i].id; int bn = 0; for(auto v:vc[u]){ if(col[v])hp[++bn] = col[v]; } sort(hp + 1,hp + 1 + bn); int cn = (bn > 0); for(int j = 1;j < bn;j++){ if(hp[j] != hp[j + 1])cn++; } //printf("u = %d cn = %d ",u,cn); if(b[i].tp == hp[bn]){ flag = 0;break; } if(b[i].tp != cn + 1){ flag = 0;break; } col[u] = b[i].tp; } if(on < n)flag = 0; if(flag){ for(int i = 1;i <= n;i++)printf("%d%c",oup[i],(i == n ? ' ' : ' ')); } else{ printf("-1 "); } return 0; }
E:我们容易发现:这个差值一定是p的倍数。当从大向小遍历时,可以发现p^ki一定是前面差值 (op[i] = 1 或 -1) sum(op[1]*(p^k[1]) + op[2]*(p^k[2])+……+op[i-1]*(p^k[i-1])) 的因子。所以sum>0时直接减去p^ki,sum = 0,加上p^ki。另外p,k都很大,需要判断差值是为(1e9 + 7)的倍数还是为0,方法是取另一个大质数模差值,如果两个都等于0,说明差值为0.
#include<bits/stdc++.h> using namespace std; #define N 1000010 #define maxn (N + 10) #define maxm (N * 2) #define pb push_back typedef long long ll; const ll INF = (1e7); const ll mod1 = ((1e9) + 7); const ll mod2 = ((1e9) + 37); ll ki[maxn]; ll f_pow(ll x,ll p,ll mod){ ll ans = 1; while(p){ if(p % 2 == 1){ ans *= x;ans %= mod; } x *= x;x %= mod;p /= 2; } return ans; } int main(){ int t;scanf("%d",&t); while(t--){ ll n,p;scanf("%lld%lld",&n,&p); for(int i = 1;i <= n;i++)scanf("%lld",&ki[i]); sort(ki + 1,ki + 1 + n); ll ans1 = 0,ans2 = 0; for(int i = n;i >= 1;i--){ if(ans1 == 0 && ans2 == 0){ ans1 += f_pow(p,ki[i],mod1); ans2 += f_pow(p,ki[i],mod2); } else{ ans1 -= f_pow(p,ki[i],mod1);ans1 = (ans1 + mod1) % mod1; ans2 -= f_pow(p,ki[i],mod2);ans2 = (ans2 + mod2) % mod2; } } printf("%lld ",ans1); } return 0; }