D:
思路:交换后暴力枚举所有前缀和再相减,取最大值
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e3+10;
int a[N];
int sum[N];
int n,k;
int ans=-1e9;
signed main()
{
cin.tie(0);
cout.tie(0);
cin>>n>>k;
if(!k)
{
for(int i=1;i<=n;i++)
{
cin>>a[i];
sum[i]=sum[i-1]+a[i];
}
for(int l=1;l<=n;l++)
for(int r=l;r<=n;r++)
{
ans=max(sum[r]-sum[l-1],ans);
}
}
else
{
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n-1;i++)
{
swap(a[i],a[i+1]);
for(int j=1;j<=n;j++) {
sum[j]=sum[j-1]+a[j];
}
for(int l=1;l<=n;l++)
for(int r=l;r<=n;r++)
{
ans=max(sum[r]-sum[l-1],ans);
}
swap(a[i],a[i+1]);
}
}
cout<<ans<<endl;
}
J:
我的代码(错误的):就过了1/5,还是多刷题吧,总之多尝试吧,看不太懂题目想表达的意思。
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
double solve(vector<int> a[],vector<int> b[],int n,int m)
{
int tt1=0;
for(int i=1;i<=n;i++)
{
vector<int>::size_type num1 = a[i].size();
if(num1>tt1)
{
tt1=i;
}
}
double ans=0;
int tag=0;
for(int i=1;i<=m;i++)
{
int st=0;
vector<int>::size_type num2 = b[i].size();
(double)num2;
for (auto item : b[i])
{
if (item == tt1)
{
st=1;
break;
}
}
if(st)
{
if(num2==1&&!tag)
{
ans+=1;
tag=1;
}
else if(num2>1)
{
ans+=(1-(1.0/num2));
}
}
}
return ans;
}
signed main()
{
cin.tie(0);
cout.tie(0);
vector<int> a[N],b[N];
int n,m,k;
cin>>n>>m>>k;
while(k--)
{
int x,y;
cin>>x>>y;
a[x].push_back(y);
b[y].push_back(x);
}
double a1=solve(a,b,n,m);
double a2=solve(b,a,m,n);
cout<<"float"<<endl;
printf("%0.8lf %0.8lf",a1,a2);
}
正确代码;
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 1e5+9;
vector<ll> gu[N];
vector<ll> gv[N];
double du[N],dv[N];
double ans_1 = 0;
double ans_2 = 0;
int main()
{
int n,m,k;cin>>n>>m>>k;
for(int i=1;i<=k;i++)
{
int u,v;cin>>u>>v;
gu[u].push_back(v);
gv[v].push_back(u);
du[u]++;//提前统计男生对应女生的数量
dv[v]++;//提前统计女生对应男生的数量
}
double ans = 1;
for(int i=1;i<=n;i++)
{
ans = 1.0;
for(auto j:gu[i])
{
ans *= (1.0 - 1.0/dv[j]);
}
ans_1 += (1-ans);
}
for(int i=1;i<=m;i++)
{
ans = 1.0;
for(auto j:gv[i])
{
ans *= (1.0 - 1.0/du[j]);
}
ans_2 += (1-ans);
}
cout<<"float\n";
printf("%.8lf %.8lf",ans_1,ans_2);
system("pause");
return 0;
}
H:
有点懊恼,总是想不明白x[i],跟y[i]为什么会作为下标来比较,p[i]用于枚举所有可能,那就索性将p[x[i]]跟p[y[i]]当做a1,a2的未知值吧当所有条件满足就输出“yes”,应该不是这样理解的,求大神指导。
#include<bits/stdc++.h>
#define int long long
using namespace std;
int p[7777];
int x[5777],y[5777],z[5777];
void solve(){
int n;
cin>>n;
for(int i=1;i<=n;i++){
cin>>x[i]>>y[i]>>z[i];
}
for(int a=1;a<=3;a++){
for(int b=1;b<=3;b++){
for(int c=1;c<=3;c++){
p[1]=a,p[2]=b,p[3]=c;
int open=1;
for(int i=1;i<=n;i++){
if(z[i]==1){
if(p[x[i]]<p[y[i]]){
}else open=0;
}else {
if(p[x[i]]>=p[y[i]]){
}else open=0;
}
}
if(open==1){
puts("YES");
return;
}
}
}
}
puts("NO");
}
signed main(){
int T=1;
cin>>T;
while(T--){
solve();
}
return 0;
}
K:
明白意思,本来就不咋会建树,还被这个样例输出误导了
参考clmm_博客的(正确的):
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/clmm_/article/details/136083717
因为我们要按“完全二叉树”的模式建树,也就是从上到下,从左往右建树。这个可以想到遍历二叉树,用的是队列
if (b % 2 == 1 && r % 2 == 0 && b >= r / 2 && b <= 1 + 2 * r)这个自己找一下规律就可以判断
void solve() {
int b, r; cin >> b >> r;
queue<int> q;//1代表黑,0代表红
q.push(1);
if (b % 2 == 1 && r % 2 == 0 && b >= r / 2 && b <= 1 + 2 * r) {
cout << "Yes" << endl;b--;
int cur = 2;
while (!q.empty()) {
int t = q.front(); q.pop();
if (t == 1) {
//要给它红孩子
if (r == 0) cout << "-1 -1" << endl;
else {
cout << cur; cur++;
cout << " " << cur << endl; cur++;
q.push(0);
q.push(0);
r -= 2;
}
}
else {
if (b == 0) cout << "-1 -1" << endl;
else {
cout << cur; cur++;
cout << " " << cur << endl; cur++;
q.push(1);
q.push(1);
b -= 2;
}
}
}
}
else cout << "No" << endl;
}
M:
我的代码(错误的):
利用两个字符串输入,暴力枚举所有组合,再用stol()将两个字符串转化为数字%36。
(只过了一半的数据,超时了还)
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int a[N];
signed main()
{
cin.tie(0);
cout.tie(0);
int t;
cin>>t;
for(int i=1;i<=t;i++)
{
cin>>a[i];
}
int count=0;
for(int i=1;i<=t;i++)
{
string s=to_string(a[i]);
for(int j=1;j<=t;j++)
{
string s1=to_string(a[j]);
int n1;
if(i!=j)
{
n1=stol(s+s1);
if(n1%36==0) count++;
}
}
}
cout<<count<<endl;
}
参考clmm_博客的(正确的):
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/clmm_/article/details/136083717
分析:看到题目的时候想,36的倍数都有什么特点,因为之前做过一道题好像也是关于什么的倍数,是有规律可循的,但在这题不行,要另找思路。
这题的正确思路是列出式子,然后变形,涉及到模运算的变换公式-CSDN博客。
原文链接:https://blog.csdn.net/clmm_/article/details/136092224
对于(ai,aj)组成的数,若是36的倍数,列出
(ai* + aj) %36 = 0,k是aj的位数
[(ai*)%36 + aj%36] % 36 = 0
[ [(ai%36)*(%36)] % 36 + aj%36 ] %36 = 0
从1-n枚举每一个数当aj,去查询有没有 ai 满足 [(ai%36)*(%36)] % 36 = 36 - aj%36。
事先用哈希表存每个数%36的结果,这样查询的时候就从哈希表的1-35找
总的时间复杂度是O(n)
#include <bits/stdc++.h>
#define int long long
#define rep(i,l,r) for(int i=1;i<=n;i++)
using namespace std;
const int N=1e5+10;
//0是任何数的倍数
string s[N];
int a[N], b[37];
void solve() {
int n; cin >> n;
rep(i, 1, n) {
cin >> s[i];
a[i] = atol(s[i].c_str());//c_str()就是将C++的string转化为C的字符串数组
b[a[i] % 36]++;
}
int ans = 0;
rep(j, 1, n) {
int k = s[j].size();//*10的位数
int pj = a[j] % 36;//后半段%36的值(a[j])%36
int key = (36 - pj) % 36;
int tpm = (int)pow(10, k) % 36;//相当于前半部分取模的值(a[i]*10的k次方)%36
for (int i = 0; i <= 35; i++) {
if ((i * tpm) % 36 == key) {
ans += b[i];
if (pj == i) ans--;//不太清楚,可能是用同一个的数组合%36也是答案,所以减一吧
}
}
}
cout << ans << endl;
}
signed main()
{
cin.tie(0);
cout.tie(0);
solve();
}