D
如果1/n是有限小数,不停乘以10,一定在有限次之后成为一个整数。
10的质因子只有2和5,只要保证分母的质因子只有2和5即可
#include#include #include <string> #include #include #include #include #include #define fo(i, l, r) for (long long i = l; i <= r; i++) #define fd(i, l, r) for (long long i = r; i >= l; i--) #define mem(x) memset(x, 0, sizeof(x)) #define ll long long #define ld double using namespace std; const int maxn = 150; const ll mod = 1e9 + 7; const double eps = 1e-9; ll read() { ll x = 0, f = 1; char ch = getchar(); while (!(ch >= '0' && ch <= '9')) { if (ch == '-') f = -1; ch = getchar(); }; while (ch >= '0' && ch <= '9') { x = x * 10 + (ch - '0'); ch = getchar(); }; return x * f; } int main() { int T,n; T=read(); while(T--){ n=read(); while(n%2==0)n/=2; while(n%5==0)n/=5; if(n>1){ printf("Yes\n"); }else{ printf("No\n"); } } return 0; }
F
仙人掌,环之间不相互影响,一个环至少删掉一条边,链无所谓,分别计算乘法原理合并
#include#include #include <string> #include #include #include #include #include #define fo(i, l, r) for (long long i = l; i <= r; i++) #define fd(i, l, r) for (long long i = r; i >= l; i--) #define mem(x) memset(x, 0, sizeof(x)) #define ll long long #define ld double using namespace std; const int maxn = 300500; const ll mod = 998244353; const double eps = 1e-9; ll read() { ll x = 0, f = 1; char ch = getchar(); while (!(ch >= '0' && ch <= '9')) { if (ch == '-') f = -1; ch = getchar(); }; while (ch >= '0' && ch <= '9') { x = x * 10 + (ch - '0'); ch = getchar(); }; return x * f; } vector<int> g[maxn]; int n,m; int d[maxn],rem; ll ans,pw[maxn*2]; void dfs(int u,int fa,int deep){ d[u] = deep; int v,sz=(int)g[u].size()-1; fo(i,0,sz){ v=g[u][i]; if(v==fa)continue; if(!d[v]) dfs(v,u,deep+1); else if(d[v]<d[u]){ ans=(ans*(pw[d[u]-d[v]+1]-1+mod))%mod; rem -= (d[u]-d[v]+1); } } } int main() { pw[0]=1;pw[1]=2; fo(i,2,500010) pw[i] = (pw[i-1]+pw[i-1])%mod; int u,v; while(scanf("%d%d",&n,&m)!=EOF){ ans=1; rem=m; fo(i,1,n){ d[i]=0; g[i].clear(); } fo(i,1,m){ u=read();v=read(); g[u].push_back(v); g[v].push_back(u); } fo(i,1,n){ if(!d[i]){ dfs(i,0,1); } } ans=(ans*pw[rem])%mod; printf("%lld\n",ans); } return 0; }
I
和之前做过的一个题很像,但是那个题需要贪心的性质为支撑,这个dp直接做就行了
#include#include #include <string> #include #include #include #include #include #define fo(i, l, r) for (long long i = l; i <= r; i++) #define fd(i, l, r) for (long long i = r; i >= l; i--) #define mem(x) memset(x, 0, sizeof(x)) #define ll long long #define ld double using namespace std; const int maxn = 100500; const ll mod = 998244353; const double eps = 1e-9; ll read() { ll x = 0, f = 1; char ch = getchar(); while (!(ch >= '0' && ch <= '9')) { if (ch == '-') f = -1; ch = getchar(); }; while (ch >= '0' && ch <= '9') { x = x * 10 + (ch - '0'); ch = getchar(); }; return x * f; } int n; int req[150][5]; char s[10][4]={"QQQ","QQW","QQE","WWW","QWW","WWE","EEE","QEE","WEE","QWE"}; char t[11] = "YVGCXZTFDB"; char a[maxn],b[maxn]; int dp[maxn][3][3][3],sum1[maxn][3][3],sum2[maxn][3],sum3[maxn],cnt[3]; int main() { fo(i,0,9){ fo(j,0,2){ if(s[i][j]=='Q')req[t[i]][0]++; if(s[i][j]=='W')req[t[i]][1]++; if(s[i][j]=='E')req[t[i]][2]++; } } while(scanf("%s",a+1)!=EOF){ n=strlen(a+1); int m = 0; fo(i,1,n){ if(a[i] != a[i-1]) b[++m] = a[i]; } swap(n,m); memset(dp,0x3f,sizeof(dp)); memset(sum1,0,sizeof(sum1)); memset(sum2,0,sizeof(sum2)); memset(sum3,0,sizeof(sum3)); int ans = mod; fo(i,1,n){ fo(t1,0,2){ fo(t2,0,2){ fo(t3,0,2){ cnt[0]=cnt[1]=cnt[2]=0; cnt[t1]++; cnt[t2]++; cnt[t3]++; if(cnt[0]!=req[b[i]][0]||cnt[1]!=req[b[i]][1]||cnt[2]!=req[b[i]][2])continue; dp[i][t1][t2][t3] = sum3[i-1]+3; if(sum1[i-1][t1][t2]) dp[i][t1][t2][t3] = min(dp[i][t1][t2][t3],sum1[i-1][t1][t2]+1); if(sum2[i-1][t1]) dp[i][t1][t2][t3] = min(dp[i][t1][t2][t3],sum2[i-1][t1]+2); if(!sum1[i][t2][t3] || (sum1[i][t2][t3] > dp[i][t1][t2][t3])){ sum1[i][t2][t3] = dp[i][t1][t2][t3]; } if(!sum2[i][t3] || (sum2[i][t3] > dp[i][t1][t2][t3])){ sum2[i][t3] = dp[i][t1][t2][t3]; } if(!sum3[i] || (sum3[i] > dp[i][t1][t2][t3])){ sum3[i] = dp[i][t1][t2][t3]; } if(i==n) ans=min(ans,dp[i][t1][t2][t3] + m); } } } } printf("%d\n",ans); } return 0; }
J
倒过来做kmp找循环节
#include#include #include <string> #include #include #include #include #include #define fo(i, l, r) for (long long i = l; i <= r; i++) #define fd(i, l, r) for (long long i = r; i >= l; i--) #define mem(x) memset(x, 0, sizeof(x)) #define ll long long #define ld double using namespace std; const int maxn = 10000500; const ll mod = 998244353; const double eps = 1e-9; ll read() { ll x = 0, f = 1; char ch = getchar(); while (!(ch >= '0' && ch <= '9')) { if (ch == '-') f = -1; ch = getchar(); }; while (ch >= '0' && ch <= '9') { x = x * 10 + (ch - '0'); ch = getchar(); }; return x * f; } int nxt[maxn]; void kmp_pre(char x[], int m, int next[]) { int i, j; j = next[0] =-1; i = 0; while (i < m) { while (-1 != j && x[i] != x[j]) j = next[j]; next[++i] = ++j; } } ll a, b,ans; char s[maxn], x[maxn]; int n, m; int main() { while (scanf("%lld%lld", &a, &b) != EOF) { scanf("%s", s + 1); n = strlen(s + 1); m = 0; fd(i, 1, n) { if (s[i] < '0' || s[i] > '9') break; x[++m] = s[i]; } kmp_pre(x+1,m,nxt); ans = a-b; fo(i,2,m){ ans=max(ans,a*i-b*(i-nxt[i])); } printf("%lld\n",ans); } return 0; }
A
直角三角形,就要看直角边在哪个点上,分两种情况讨论,然后围绕着直角点极角排序,找垂直的边。
#pragma GCC optimize(2) #include#include #include <string> #include #include #include #include #include #include <set> #include #include #include
E
给某些节点一个通过量的限制,从某些点出发、一些终点,可以向网络流的方向考虑,如何建图?
分析性质,假如说一个机器人从格点的一个边进入,再从某个边出,如果有人跟他反着来,则必然会逆着他走的路到第一行。
如果有人顺着它的路线走,那么会跟他走进同一个终点。
也就是说,如果这个节点,它拐弯了,那就只能一个机器人走一次。
如果它没拐弯,横着走过去之后,竖着走过去不会和原来横着走的路径有同样或者相反的结果,也就是能走两次。
拆点,把每个点拆成横竖两个点,相邻的恒竖相连,可以走2次,同一个点横竖相连,割这个边就说明在这个点放了转向器,只能走一次。
#include#include #include <string> #include #include #include #include #include #define fo(i, l, r) for (int i = l; i <= r; i++) #define fd(i, l, r) for (int i = r; i >= l; i--) #define mem(x) memset(x, 0, sizeof(x)) #define ll long long using namespace std; const int maxn = 300050; ll read() { ll x = 0, f = 1; char ch = getchar(); while (!(ch >= '0' && ch <= '9')) { if (ch == '-') f = -1; ch = getchar(); }; while (ch >= '0' && ch <= '9') { x = x * 10 + (ch - '0'); ch = getchar(); }; return x * f; } const int MAXN = 200010; //点数的最大值 const int MAXM = 1600010; //边数的最大值 const int INF = 0x3f3f3f3f; struct Edge { int to, next, cap, flow; } edge[MAXM]; //注意是 MAXM int tol; int head[MAXN]; int gap[MAXN], dep[MAXN], cur[MAXN]; void init() { tol = 0; memset(head,-1, sizeof(head)); } void addedge(int u, int v, int w, int rw = 0) { edge[tol].to = v; edge[tol].cap = w; edge[tol].flow = 0; edge[tol].next = head[u]; head[u] = tol++; edge[tol].to = u; edge[tol].cap = rw; edge[tol].flow = 0; edge[tol].next = head[v]; head[v] = tol++; } int Q[MAXN]; void BFS(int start, int end) { memset(dep,-1, sizeof(dep)); memset(gap, 0, sizeof(gap)); gap[0] = 1; int front = 0, rear = 0; dep[end] = 0; Q[rear++] = end; while (front != rear) { int u = Q[front++]; for (int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].to; if (dep[v] != -1) continue; Q[rear++] = v; dep[v] = dep[u] + 1; gap[dep[v]]++; } } } int S[MAXN]; int sap(int start, int end, int N) { BFS(start, end); memcpy(cur, head, sizeof(head)); int top = 0; int u = start; int ans = 0; while (dep[start] < N) { if (u == end) { int Min = INF; int inser; for (int i = 0; i < top; i++) if (Min > edge[S[i]].cap - edge[S[i]].flow) { Min = edge[S[i]].cap - edge[S[i]].flow; inser = i; } for (int i = 0; i < top; i++) { edge[S[i]].flow += Min; edge[S[i] ^ 1].flow -= Min; } ans += Min; top = inser; u = edge[S[top] ^ 1].to; continue; } bool flag = false; int v; for (int i = cur[u]; i != -1; i = edge[i].next) { v = edge[i].to; if (edge[i].cap - edge[i].flow && dep[v] + 1 == dep[u]) { flag = true; cur[u] = i; break; } } if (flag) { S[top++] = cur[u]; u = v; continue; } int Min = N; for (int i = head[u]; i != -1; i = edge[i].next) if (edge[i].cap - edge[i].flow && dep[edge[i].to] < Min) { Min = dep[edge[i].to]; cur[u] = i; } gap[dep[u]]--; if (!gap[dep[u]]) return ans; dep[u] = Min + 1; gap[dep[u]]++; if (u != start) u = edge[S[--top] ^ 1].to; } return ans; } int n,m,a,b; char mp[105][105]; inline int tran(int y,int x,int dir){ int t = (y-1)*m+x; if(dir) t+=n*m; return t; } inline bool jud(int y,int x){ return y>=1&&y<=n&&x>=1&&x<=m&&mp[y][x]=='0'; } int main() { int T=read(); while(T--){ init(); n=read();m=read();a=read();b=read(); fo(i,1,n){ scanf("%s",mp[i]+1); } fo(i,1,n){ fo(j,1,m){ if(jud(i-1,j)) addedge(tran(i,j,0),tran(i-1,j,0),1); if(jud(i+1,j)) addedge(tran(i,j,0),tran(i+1,j,0),1); if(jud(i,j-1)) addedge(tran(i,j,1),tran(i,j-1,1),1); if(jud(i,j+1)) addedge(tran(i,j,1),tran(i,j+1,1),1); addedge(tran(i,j,0),tran(i,j,1),1); addedge(tran(i,j,1),tran(i,j,0),1); } } int u; fo(i,1,a){ u=read(); addedge(0,tran(1,u,0),1); } fo(i,1,b){ u=read(); addedge(tran(n,u,0),n*m*2+1,1); } if(sap(0,n*m*2+1,n*m*2+2)==a){ printf("Yes\n"); }else{ printf("No\n"); } } return 0; }