AC了
总的来说,比上次友善多了,这才是我熟悉的暴力杯。
就做了3个满的,7道全骗(年轻人,来骗,来,偷袭!
1 幸运数 话不多说,马上开爆 机房电脑跑了几十秒才出答案
就问你出没出答案吧
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long ll;
bool check(int x)
{
vector<int> vec;
while(x)
{
vec.push_back(x%10);
x/=10;
}
int sz=vec.size();
if(sz%2!=0)return false;
int a=0,b=0;
for(int i=0;i<sz/2;i++)a+=vec[i];
for(int i=sz/2;i<sz;i++)b+=vec[i];
return a==b;
}
//4430091
int main()
{
int ans=0;
cout<<"test:"<<check(22)<<" "<<check(22)<<'\n';
for(int i=1;i<=100000000;i++)
{
if(check(i))ans++;
}
cout<<ans;
return 0;
}
2 胜利的方案数。现在想想好像做错了 ,, 寄,因为必须保证开始连续7次胜利的前一场输掉,应该是枚举到23-1=22
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
ll C(ll n,ll m)
{
ll res=1;
//for(ll i=n;i>=n-m+1;i--)res*=i;
for(ll i=n;i>=n-m+1;i--)res*=i;
for(ll i=1;i<=m;i++)res/=i;
return res;
}
ll ksm(ll x,ll a)
{
ll res=1;
while(a)
{
if(a&1)res*=x;
x*=x;
a>>=1;
}
return res;
}
//4540385
int main()
{
ll res=0;
// cout<<C(0,0)<<" "<<C(1,0)<<'\n';
for(ll i=0;i<=23;i++)
{
for(ll j=0;j<=min(9ll,i);j++)
{
res+=C(i,j);
}
}
cout<<res;
return 0;
}
3 平方差 不知道满分做法, x=a^2-b^2=(a+b)(a-b),这启发我们因式分解x,若x能分为a0,a1。a0+a1 为偶数 则可以把 a0*a1表示为 上面平方差形式,因此可以算作一个贡献。时间复杂度 O(n^1.5)
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
int l,r;
int ans;
int main()
{
scanf("%d%d",&l,&r);
for(int i=l;i<=r;i++)
{
int x=i;
bool flag=false;
for(int j=1;j<=x/j;j++)
{
if(x%j==0)
{
int t=x/j;
if((j+t)%2==0)
{
flag=true;
break;
}
}
}
if(flag)ans++;
}
printf("%d",ans);
return 0;
}
4 反转字符串 , dp【i】【j】,表示 下标 i到 j 的子字符串 反转后 比原来大还是小还是相等。若i>j 则 表示空字符串 ,也即相等 。因此dp【i】【j】(i<j) 等于0
我们观察 dp[i][j]与dp【i+1】【j-1】的关系,不难发现可以O(1)完成转移,因此DP
O(n方) 切了。
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=5e3+10;
char s[N];
int n;
int dp[N][N];//0 equal 1 elss than after reverse -1 less than after reverse
ll ans;
int main()
{
scanf("%s",s+1);
n=strlen(s+1);
dp[n][n]=0;
for(int i=n-1;i>=1;i--)
{
for(int j=i;j<=n;j++)
{
int a=s[i]-'0',b=s[j]-'0';
if(a>b)dp[i][j]=1;
else if(b==a)
{
dp[i][j]=dp[i+1][j-1];
}
else dp[i][j]=-1;
}
}
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
if(dp[i][j]==1)ans++;
}
}
printf("%lld",ans);
return 0;
}
5 颜色平衡树 不会,对每个节点dfs一遍, O(n方)偏分
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
using namespace std;
typedef long long ll;
const int N=2e5+10;
int head[N];
int color[N];
int n;
struct node{
int to,nxt;
}edge[N];
int idx;
map<int,int> mp;
int ans;
void add(int from,int to)
{
edge[idx].to=to;
edge[idx].nxt=head[from];
head[from]=idx++;
}
void dfs(int u)
{
mp[color[u]]++;
for(int i=head[u];~i;i=edge[i].nxt)
{
int v=edge[i].to;
dfs(v);
}
}
int main()
{
memset(head,-1,sizeof head);
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
int fa;
scanf("%d%d",&color[i],&fa);
if(fa!=0)add(fa,i);
}
for(int i=1;i<=n;i++)
{
mp.clear();
dfs(i);
int cm=(*mp.begin()).second;
bool flag=true;
for(map<int,int>::iterator i=mp.begin();i!=mp.end();i++)
{
if((*i).second!=cm)
{
flag=false;
break;
}
}
if(flag)ans++;
}
printf("%d",ans);
return 0;
}
6
两层二进制枚举 很蠢 的骗了30%分 明明 可以写3^n 的 太蠢了
7 数字电路好像叫这名r
Floyd 骗 30%
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
using namespace std;
typedef long long ll;
const int N=5e3+10;
const int INF=0x3f3f3f3f;
int n,m,q;
int dist[N][N];
int main()
{
scanf("%d%d%d",&n,&m,&q);
memset(dist,0x3f,sizeof dist);
// for(int i=0;i<=n;i++)dist[i][i]=0;
for(int i=1;i<=m;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
int temp=dist[a][b];
if(temp!=INF)dist[a][b]=dist[b][a]=max(c,temp);
else dist[a][b]=dist[b][a]=c;
}
for(int k=1;k<=n;k++)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
//dist[a][b]=max(dist[a][b],min(dist[a][k],dist[k][b]));
int temp=min(dist[i][k],dist[k][j]);
if(dist[i][k]==INF||dist[k][j]==INF)temp=INF;
if(dist[i][j]==INF)dist[i][j]=temp;
else {
if(temp!=INF)dist[i][j]=max(dist[i][j],temp);
}
}
}
}
// for(int i=1;i<=n;i++)
// {
// for(int j=1;j<=n;j++)cout<<dist[i][j]<<" ";
// cout<<'\n';
// }
while(q--)
{
int a,b;
scanf("%d%d",&a,&b);
if(dist[a][b]!=INF)printf("%d\n",dist[a][b]);
else puts("-1");
}
return 0;
}
8 异或和 前缀和 O(n方) 骗60% 正解 舍友说用二进制拆分 O(30n)
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=1e5+10;
ll a[N];
ll d[N];
int n;
ll ans;
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<=n;i++)
{
d[i]=a[i];
d[i]^=d[i-1];
}
for(int i=1;i<=n;i++)
{
for(int j=i;j<=n;j++)
{
ans+=(d[j]^d[i-1]);
}
}
printf("%lld",ans);
return 0;
}
9 很想数独的一道题 O(2^nm)暴力dfs开骗
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cctype>
using namespace std;
typedef long long ll;
const int N=15;
int n,m;
char g[N][N];
bool flag=false;
int dx[]={-1,-1,-1,0,0,1,1,1,0};
int dy[]={1,0,-1,1,-1,1,0,-1,0};
int nums[N][N];
inline bool check()
{
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
if(g[i][j]=='_')continue;
else
{
int target=g[i][j]-'0';
int tot=0;
for(int k=0;k<9;k++)
{
int a=i+dx[k],b=j+dy[k];
if(a<0||a>=n||b<0||b>=m)continue;
if(nums[a][b]==1)tot++;
}
if(tot!=target)return false;
}
}
}
return true;
}
void dfs(int a,int b)
{
if(flag)return ;
if(a==n)
{
if(check())
{
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)printf("%d",nums[i][j]);
puts("");
}
flag=true;
}
return ;
}
if(b==n){
dfs(a+1,0);
return ;
}
nums[a][b]=1;
dfs(a,b+1);
nums[a][b]=0;
dfs(a,b+1);
return ;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)scanf("%s",g[i]);
dfs(0,0);
return 0;
}
10 抛硬币 O(nlogn) 。 假设每个银币被翻转了 n次,因此 除了第一枚硬币,其他硬币的翻转次数应该为偶数。 我们从前考虑每一个硬币 ,第一个硬币一定要翻转一次,因此后面每个硬币 都会被翻转一次,我们从前往后考虑每个硬币 ,类似埃氏筛法的就能 暴力骗30%分 (前提代码没错 QAQ
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=5e6+10;
int n;
int cnt[N];
ll ans;
// o(nlogn)
int main()
{
scanf("%d",&n);
ans=1;
for(int i=2;i<=n;i++)
{
if(cnt[i]%2==0){
ans++;
for(int j=i*2;j<=n;j+=i)cnt[j]++;
}
}
printf("%lld",ans);
return 0;
}
没进过决赛 希望满足一次 TNT
-------------------更新----------------
省一 舒服了