根据题意可知,求连续两个质数相加除以2向下取整后是否还是质数,因为是连续的两个质数,所以取中位数后一定不会是质数,1除外
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| #include <bits/stdc++.h> using namespace std; typedef long long LL; LL t , n; int main() { scanf("%lld" , &t); while (t --) { scanf("%lld" , &n); if (n == 1) printf("YES\n"); else printf("NO\n"); } return 0; }
|
给定一个字符串,求这个字符串有多少个子序列满足由前缀nunhehheh和k个a(k>0)组成。
例如nunhehhehaaaaaa就是符合要求的,但是nunhehheh和nunhehhehoooaaa是不符合要求的。
这是一个dp模型,求一个字符串的所有子序列中有多少个s(s是一个字符串),这里只是多了后缀a,我们先找字符串包含多少个nunhehheh,开一个dp数组,dp[i]表示匹配到匹配到第k个字符出现了前i个字串的数量,例如dp[1]表示出现n的数量,dp[3]表示出现nun的数量,遍历字符串,将对应的字符,dp[i]=(dp[i-1]+dp[i])%mod
最后dp[9]就是出现nunhehheh的数量,用dp[10]表示前缀nunhehheh和k个a(k>0)组成的字符串数量,考虑给后面加上一个a,那么之前满足条件的字符串可以加a也可以不加,而dp[9]必须加上这个a才能满足条件,所以dp[10]=(dp[10]+dp[9])%mod
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| #include <bits/stdc++.h> #define endl '\n' #define ios ios::sync_with_stdio(0);cin.tie(0);cout.tie(0) using namespace std; typedef long long ll; ll mod=998244353; ll dp[20],T; int main() { ios; cin>>T; while(T--){ memset(dp,0,sizeof dp); string s; cin>>s; int len=s.size(); for(int i=0;i<len;i++){ if(s[i]=='n'){ dp[1]++; dp[3]=(dp[3]+dp[2])%mod; } else if(s[i]=='u') dp[2]=(dp[1]+dp[2])%mod; else if(s[i]=='h'){ dp[9]=(dp[9]+dp[8])%mod; dp[7]=(dp[7]+dp[6])%mod; dp[6]=(dp[6]+dp[5])%mod; dp[4]=(dp[4]+dp[3])%mod; } else if(s[i]=='e'){ dp[5]=(dp[4]+dp[5])%mod; dp[8]=(dp[8]+dp[7])%mod; } else if(s[i]=='a') dp[10]=(dp[10]*2%mod+dp[9])%mod; } cout<<dp[10]<<endl; } return 0; }
|
分类讨论,数学问题,我用小数写的,但是其实用longlong更好,不会有精度问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| #include <bits/stdc++.h> #define endl '\n' #define ios ios::sync_with_stdio(0);cin.tie(0);cout.tie(0) using namespace std; typedef long long ll; const ll mod=998244353; int T; double a,b,c,x0,y0,x1,y1,y2; double f1(ll y){ return (-b+sqrt(b*b-4*a*(c-y0)))/(2*a); } double f2(ll y){ return (-b-sqrt(b*b-4*a*(c-y0)))/(2*a); } double work(double x){ return a*x*x+b*x+c; } int main() { ios; cin>>T; while(T--){ cin>>a>>b>>c; cin>>x0>>x1>>y0>>y1>>y2; if(work(x0)==y0 || work(x1)==y0) cout<<"No"<<endl; else{ double p=-b/(2*a); if(work(p)<=y0 || p>=x1 || (f1(y0)>=x0 && f1(y0)<=x1)) cout<<"No"<<endl; else if(f2(y0)>x0 && f2(y0)<x1) cout<<"Yes"<<endl; else{ if(work(x1)<=y2 && f2(y0)>x1 && f2(y0)<x1+x1-x0) cout<<"Yes"<<endl; else cout<<"No"<<endl; } } } return 0; }
|
更好的代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| #include <bits/stdc++.h> #define ios ios::sync_with_stdio(false), cin.tie(0), cout.tie(0); using namespace std; typedef unsigned long long ull; typedef long long ll; const ll mod = 998244353;
ll a, b, c, xa, xb, ya, yb, yc;
ll changdu(ll x){ ll res = a * x * x + b * x + c; return res; }
int main() { ios; int t; cin >> t; while(t --){ cin >> a >> b >> c >> xa >> xb >> ya >> yb >> yc; ll lena = changdu(xb), lenb = changdu(0 - xa + xb * 2), len = changdu(xa); if (len <= ya) cout << "No\n"; else if (lena == ya || lena > yc) cout << "No\n"; else if (lena < ya) cout << "Yes\n"; else{ if (lenb >= ya) cout << "No\n"; else cout << "Yes\n"; } }
return 0; }
|
比赛的时候一直在想从边权大的开始出发,把所有能到达这个点的所有点答案加一,利用线段树去维护,但是到后面块太多了,维护不了,于是就搁置了,正解是从边权小的开始枚举,对于当前点,把和这个点相邻的点都合并到当前点,让当前点作为祖先,循环往复,到最后每一个点距离根节点的距离就是答案,原理就是因为是按照点权从小到大枚举的,因此每一个点都不可能越过根节点到达其他分支的节点,所以一个节点可以到达的节点就是这个点距离和根节点之间的点,也就是距离。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
| #include <bits/stdc++.h> #define endl '\n' #define ios ios::sync_with_stdio(0);cin.tie(0);cout.tie(0) using namespace std; const int N=2e5+100; struct node{ int id,val; }arr[N]; int T,n,u,v; int fa[N],ans[N]; bool vis[N]; vector<int> ve[N]; bool cmp(node a,node b){ return a.val<b.val; } int find(int x){ if(x==fa[x]) return x; else{ int tmp=fa[x]; fa[x]=find(fa[x]); ans[x]+=ans[tmp]; return fa[x]; } } void init(){ for(int i=1;i<=n;i++){ fa[i]=i; ans[i]=0; ve[i].clear(); vis[i]=0; } } int main() { ios; cin>>T; while(T--){ cin>>n; init(); for(int i=1;i<n;i++){ cin>>u>>v; ve[u].push_back(v); ve[v].push_back(u); } for(int i=1;i<=n;i++){ cin>>arr[i].val; arr[i].id=i; } sort(arr+1,arr+1+n,cmp); for(int i=1;i<=n;i++){ int now=arr[i].id; for(int j=0;j<ve[now].size();j++){ if(vis[ve[now][j]]){ int fu=find(ve[now][j]); ans[fu]=1; fa[fu]=now; } } vis[now]=1; } for(int i=1;i<=n;i++){ find(i); cout<<ans[i]+1<<endl; } } return 0; }
|
Monopoly
$a1,a2,a3…an$
首先求一个前缀和,$S=K*pre[n]+pre[i]$,考虑pre[n]大于0的情况,这个时候pre[i]一定小于等于S,对pre[n]取模,发现S和pre[i]同余,也就是求一个pre[i]使得K最小,并且在K相同条件下i尽可能小,考虑维护n个容器,每一个容器对应一个余数,容器中放置所有同余的前缀和,给定一个x就去相对应的容器中二分找到小于等于x的最大前缀,即是答案。
需要特别注意的是,前缀和可能是负数,而给定的x是负数,这个时候x和前缀和是同余的,但是符号相反,这里需要特别处理一下。
如果pre[n]小于0,则所有数字取反即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
| #include <iostream> #include <string.h> #include <map> #include <algorithm> #include <vector> #define endl '\n' #define ios ios::sync_with_stdio(0);cin.tie(0);cout.tie(0) using namespace std; const int N=2e5+100; typedef long long ll; int n,m; ll arr[N]; vector<ll> cis[N]; int tot,T; map<ll,int> mp,mp2; void init(){ mp.clear(); mp2.clear(); for(int i=1;i<=tot;i++) cis[i].clear(); tot=0; } int main() { ios; cin>>T; while(T--){ init(); cin>>n>>m; for(int i=1;i<=n;i++){ cin>>arr[i]; arr[i]+=arr[i-1]; } ll sum=arr[n]; int flag=0; if(sum<0){ for(int i=1;i<=n;i++) arr[i]=-arr[i]; sum=-sum; flag=1; } for(int i=1;i<=n;i++) if(!mp2[arr[i]]) mp2[arr[i]]=i;; if(sum!=0){ for(int i=1;i<=n;i++){ ll now=(arr[i]%sum+sum)%sum; if(!mp[now]) mp[now]=++tot; cis[mp[now]].push_back(arr[i]); } } for(int i=1;i<=tot;i++) sort(cis[i].begin(),cis[i].end()); while(m--){ ll x; cin>>x; if(flag) x=-x; if(x==0){ cout<<0<<endl; continue; } if(sum==0){ if(mp2[x]) cout<<mp2[x]<<endl; else cout<<-1<<endl; continue; } if(!mp[(x%sum+sum)%sum]){ cout<<-1<<endl; continue; } int now=mp[(x%sum+sum)%sum]; auto it=upper_bound(cis[now].begin(),cis[now].end(),x); if(it==cis[now].begin()) cout<<-1<<endl; else{ it--; cout<<(x-*it)/sum*n+mp2[*it]<<endl; } } } return 0; }
|