2018.9.3模拟赛
\(T1\)
直接考虑二分就可以了。。。
二分spfa判断,直接AC一发!
#include<bits/stdc++.h>
using namespace std;
struct edge{
int to,nxt;
double val;
} e[400010];
int l1,l2,r1,r2,xz,n,m,cnt = 0,head[50010],fa[50010],u[200010],v[200010],x[5010],dis[50010],vis[50010],s,t,que[200010],w[200010];
double l = 15000,r;
inline int read (){
int q=0,f=1;char ch = getchar();
while(!isdigit(ch)) {
if(ch=='-')f=-1;ch=getchar();
}
while(isdigit(ch)){
q=q*10+ch-'0';ch=getchar();
}
return q*f;
}
inline double minn(double a,double b)
{
if (a < b) return a; else return b;
}
inline double maxx(double a,double b)
{
if (a > b) return a; else return b;
}
inline void add(int a,int b,double c)
{
e[++cnt].to = b;
e[cnt].val = c;
e[cnt].nxt = head[a];
head[a] = cnt;
}
inline bool Spfa(int xx)
{
memset(dis,0x3f,sizeof(dis));
memset(vis,0,sizeof(vis));
int ll = 0,rr = 1;
que[1] = s;
vis[s] = 1;
dis[s] = 0;
while (ll < rr)
{
ll ++;
int u = que[ll];
vis[u] = 0;
for (int i = head[u]; i ; i = e[i].nxt)
{
if (e[i].val >= xx && dis[e[i].to] > dis[u] + 1)
{
dis[e[i].to] = dis[u] + 1;
if (!vis[e[i].to])
{
rr ++;
que[rr] = e[i].to;
vis[e[i].to] = 1;
}
}
}
}
if (dis[t] != 0x3f3f3f3f) return 1; else return 0;
}
inline bool Spfaa(int xx)
{
memset(dis,0x3f,sizeof(dis));
memset(vis,0,sizeof(vis));
int ll = 0,rr = 1;
que[1] = s;
vis[s] = 1;
dis[s] = 0;
while (ll < rr)
{
ll ++;
int u = que[ll];
vis[u] = 0;
for (int i = head[u]; i ; i = e[i].nxt)
{
if (e[i].val <= xx && e[i].val >= l1 * 1.000 && dis[e[i].to] > dis[u] + 1)
{
dis[e[i].to] = dis[u] + 1;
if (!vis[e[i].to])
{
rr ++;
que[rr] = e[i].to;
vis[e[i].to] = 1;
}
}
}
}
if (dis[t] != 0x3f3f3f3f) return 1; else return 0;
}
int main()
{
freopen("trip.in","r",stdin);
freopen("trip.out","w",stdout);
n = read();
m = read();
for (int i = 1; i <= m; i ++)
{
u[i] = read();
v[i] = read();
w[i] = read();
}
for (int i = 1; i <= n; i ++)
{
int num = read();
for (int j = 1; j <= num; j ++)
{
fa[read()] = i;
}
}
for (int i = 1; i <= n; i ++)
{
x[i] = read();
}
s = read();
t = read();
for (int i = 1; i <= m; i ++)
{
double ww = w[i] * (x[fa[u[i]]] + x[fa[v[i]]]) * 1.000 / 200;
add(u[i],v[i],ww);
add(v[i],u[i],ww);
l = minn(l,ww);
r = maxx(r,ww);
}
l1 = l;
l2 = l;
r1 = r;
r2 = r;
if (r1 - r != 0)
{
r1 ++;
r2 ++;
}
//cout<<l1<<' '<<r1<<endl;
while (l1 < r1)
{
int mid = (l1 + r1) >> 1;
if (Spfa(mid)) l1 = mid + 1; else r1 = mid;
//cout<<l1<<' '<<r1<<endl;
}
while (!Spfa(l1)) l1 --;
l2 = l1;
while (l2 < r2)
{
int mid = (l2 + r2) >> 1;
if (Spfaa(mid)) r2 = mid; else l2 = mid + 1;
}
while (!Spfaa(l2)) l2 ++;
printf("%d %d",l1,l2);
return 0;
}
\(T2\)
推式子题。。。其实如果不想推的话可以直接高精。。。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 4010;
const int maxm = 100010;
inline int read (){
int q=0,f=1;char ch = getchar();
while(!isdigit(ch)) {
if(ch=='-')f=-1;ch=getchar();
}
while(isdigit(ch)){
q=q*10+ch-'0';ch=getchar();
}
return q*f;
}
const int lim = 100000000;
char s[100010];
int n,k;
int kth[maxm];
ll a[maxn];
bool vis[maxm];
int cnt = 1;
int main () {
freopen("array.in","r",stdin);
freopen("array.out","w",stdout);
n = read();scanf("%s",s);
int l = 4000;
int len = strlen(s);
for(int i = len - 1;i >= 0; --i) {
a[l] += (s[i] - '0') * cnt;
cnt = (cnt<<3) + (cnt << 1);
if(cnt == lim) l--,cnt = 1;
}
int tmp;
for(tmp = 4000;a[tmp] == 0;a[tmp] = lim - 1,tmp--);
--a[tmp];
for(int i = 1;i <= n; ++i) {
for(int j = l;j < 4000; ++j) {
ll x = a[j] / i;
a[j + 1] += lim*(a[j] - x * i);
a[j] = x;
}
kth[n - i + 1] = a[4000] % i + 1;
a[4000]/=i;
while(a[l] == 0) ++l;
}
int mx = max(0,n - 6100);
for(int i = 1;i <= mx; ++i) {
printf("%d ",i);
}
for(int i = mx + 1;i <= n; ++i) {
int j,tot;
for(j = mx + 1,tot = 0;tot < kth[i]; ++j) {
if(!vis[j]) ++tot;
}
vis[--j] = 1;
printf("%d ",j);
}
return 0;
}
\(T3\)
照样推式子,然后枚举约数就可以了。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll a[100];
ll p[100];
ll n;
ll d[3000010];
ll cnt;
ll N;
inline ll read (){
ll q=0,f=1;char ch = getchar();
while(!isdigit(ch)) {
if(ch=='-')f=-1;ch=getchar();
}
while(isdigit(ch)){
q=q*10+ch-'0';ch=getchar();
}
return q*f;
}
inline void dfs(ll now,ll x) {
if(now > cnt) {
if(x < N && !(N - x & 1) && ( N - x >> 1) % x == 0) d[++d[0]] = N - x;
return;
}
ll T = 1;
for(int i = 0;i <= p[now]; ++i) {
dfs(now + 1,x * T);
T *= a[now];
}
}
int main () {
freopen("math.in","r",stdin);
freopen("math.out","w",stdout);
n = read();
N = n;
if(n == 1) {
return puts("0");
}
for(ll i = 2;i * i <= n; ++i) {
if(!(n % i)) {
n /= i;a[++cnt] = i;
p[cnt] = 1;
while(!(n % i)) n /= i,++p[cnt];
}
}
if(n > 1) {
a[++cnt] = n;
p[cnt] = 1;
}
dfs(1,1);
sort(d+1,d+d[0] + 1);
printf("%d ",d[0]);
for(int i = 1;i <= d[0]; ++i) {
printf("%d ",d[i]);
}
return 0;
}