懒得分类了
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
int main()
{
int a[10]={1,2,3,4,5,6,8,9,10,12};
int s1,s2,s3,s4,s5;
int cnt=0;
do
{
s1=a[1]+a[2]+a[3]+a[4];
s2=a[0]+a[2]+a[5]+a[8];
s3=a[0]+a[3]+a[6]+a[9];
s4=a[1]+a[5]+a[7]+a[9];
s5=a[8]+a[7]+a[6]+a[4];
if(s1==s2&&s2==s3&&s3==s4&&s4==)
cnt++;
}while(next_permutation(a,a+10));
printf("%d\n",cnt/10);
}
这回是真的喜欢算法这种东西了,看到一位大佬的博客https://blog.csdn.net/nameofcsdn/article/details/52833504
数独欸,最喜欢了,于是。。。
八皇后
#include<iostream>
using namespace std;
int cheese_table[8][8];
int queen[8];//记录列数
int lastqueen=-1;//the position that queen is put
int solution=0;
int search_line(int i,int j){//from line i,column j search
for(;j<8;j++)
if(cheese_table[i][j]==0)
return j;
return -1;
}
void set_queen(int i,int j){
cheese_table[i][j]=-1;
queen[i]=j;
for(int temp=0;temp<8;temp++){
if(cheese_table[temp][j]!=-1)
cheese_table[temp][j]++;
}
for(int temp=0;temp<8;temp++)
if(cheese_table[i][temp]!=-1)
cheese_table[i][temp]++;
int tempj=j+1;
for(int tempi=i+1;tempj<8&&tempj<8;tempi++)
cheese_table[tempi][tempj++]++;
tempj=j-1;
for(int tempi=i-1;tempi<8&&tempj>=0;tempi++)
cheese_table[tempi][tempj--]++;
tempj=j+1;
for(int tempi=i-1;tempi>=0&&tempj<8;tempi--)
cheese_table[tempi][tempj++]++;
tempj=j-1;
for(int tempi=i-1;tempi>=0&&tempj>=0;tempi--)
cheese_table[tempi][tempj--]++;
return ;
}
void uptake_queen(int i){
int j=queen[i];
for(int temp=0;temp<8;temp++){
if(cheese_table[temp][j]!=-1)
cheese_table[temp][j]--;
}
for(int temp=0;temp<8;temp++)
if(cheese_table[i][temp]!=-1) cheese_table[i][temp]--;
int tempj=j+1;
for(int tempi=i+1;tempi<8&&tempj<8;tempi++)
cheese_table[tempi][tempj++]--;
tempj=j-1;
for(int tempi=i-1;tempi<8&&tempj>=0;tempi++)
cheese_table[tempi][tempj--]--;
tempj=j+1;
for(int tempi=i-1;tempi>=0&&tempj<8;tempi--)
cheese_table[tempi][tempj++]--;
tempj=j-1;
for(int tempi=i-1;tempi>=0&&tempj>=0;tempi--)
cheese_table[tempi][tempj--]--;
cheese_table[i][j]=0;
return ;
}
int main(){
for(int i=0;i<8;i++)
for(int j=0;j<8;j++)
cheese_table[i][j]=0;
for(int i=0;;i++){
int j=search_line(i,lastqueen+1);
if(j==-1) {
if(i==0) break;
uptake_queen(i-1);
lastqueen=queen[i-1];
i-=2;
}
else{
lastqueen=-1;
set_queen(i,j);
if(i==7){
solution++;
uptake_queen(7);
lastqueen=j;
i--;
}
}
}
cout<<solution<<endl;
return 0;
}
迷瘴
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 13936 Accepted Submission(s): 4519
Problem Description
通过悬崖的yifenfei,又面临着幽谷的考验——
幽谷周围瘴气弥漫,静的可怕,隐约可见地上堆满了骷髅。由于此处长年不见天日,导致空气中布满了毒素,一旦吸入体内,便会全身溃烂而死。
幸好yifenfei早有防备,提前备好了解药材料(各种浓度的万能药水)。现在只需按照配置成不同比例的浓度。
现已知yifenfei随身携带有n种浓度的万能药水,体积V都相同,浓度则分别为Pi%。并且知道,针对当时幽谷的瘴气情况,只需选择部分或者全部的万能药水,然后配置出浓度不大于 W%的药水即可解毒。
现在的问题是:如何配置此药,能得到最大体积的当前可用的解药呢?
特别说明:由于幽谷内设备的限制,只允许把一种已有的药全部混入另一种之中(即:不能出现对一种药只取它的一部分这样的操作)。
Input
输入数据的第一行是一个整数C,表示测试数据的组数;
每组测试数据包含2行,首先一行给出三个正整数n,V,W(1<=n,V,W<=100);
接着一行是n个整数,表示n种药水的浓度Pi%(1<=Pi<=100)。
Output
对于每组测试数据,请输出一个整数和一个浮点数;
其中整数表示解药的最大体积,浮点数表示解药的浓度(四舍五入保留2位小数);
如果不能配出满足要求的的解药,则请输出0 0.00。
Sample Input
3 1 100 10 100 2 100 24 20 30 3 100 24 20 20 30
Sample Output
0 0.00 100 0.20 300 0.23
#include<stdio.h>
#include<algorithm>
#include<iostream>
using namespace std;
int a[110];
int main(){
int t;
cin>>t;
while(t--){
int n,v,w;
cin>>n>>v>>w;
double p=0;int vv=0;//为了方便更新p,直接得出答案
for(int i=1;i<=n;i++)
cin>>a[i];
sort(a+1,a+1+n);
for(int i=1;i<=n;i++){
if((p*vv+a[i]*v)<=w*(vv+v )){
vv+=v;//更新
p=(p*(vv-v)+a[i]*v)/vv;//之前我更新用的不是原来的值,而是新的值
}
else break;
}
printf("%d %.2lf\n",vv,p/100);
}
return 0;
}
细节总是出错。
之前抄了模拟退火的模板,结果似懂非懂,还是要结合题目
逆序数
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int n=1e5+5;
int a[n];
int ans[n];
ll solve(int l,int r){
int mid=(l+r)>>1;
if(l==r){
return 0;
}
ll num=0;
num+=solve(l,mid);
num+=solve(mid+1,r);
for(int i=l,j=mid+1,k=0;i<=mid||j<=r;k++){
if(i>mid) ans[k]=a[j++];
else if(j>r) ans[k]=a[i++];
else if(a[i]<=a[j]) ans[k]=a[i++];
else {
ans[k]=a[j++];
num+=mid-i+1;
}
}
for(int i=0;i<(r-l);i++){
a[l+i]=ans[i];
}
return num;
}
int main(){
int n;
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",a+i);
}
printf("%lld\n",solve(0,n-1));
return 0;
}
归并时同时计算逆序数,想到这个关键是,归并从相邻的开始,如果逆序,就会+1,然后就为顺序了,在以此为基础(可以以此为基础,那是因为相邻的内部调整不会影响外面的结果),以及在两部分已经排序的前提下,如果左边的有一个大于右边一部分的一个,那么左边的那一个后面都大于它,显而易见,直接加上,也利用了前面的已经排序的都是顺序的,也就是说利用了排序,为什么这么用呢。由于逆序对之类的是要比较大小的,从而排序,结合:像交换排序,如果第一个大于后面的一个数,计数一次,再轮到第二个数,同样前面的不会影响后面的,这是朴实无华的做法,作为基础,但如果是直接交换排序的的话,太过整体了,因为,直接找到最小,换到前面的话,这个步骤并不一定是逆序对的数量,中间可以有比开头大的,也就是说前面最好已经排过序了,同样前面要有比后面大的值,同时要前面都比他小,后面都比他大,排序的时候同时计数,而他显然处于另一部分,也就是说,归并排序的合并阶段的比较。
Inversion
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 6820 Accepted Submission(s): 2328
Problem Description
bobo has a sequence a1,a2,…,an. He is allowed to swap two adjacent numbers for no more than k times.
Find the minimum number of inversions after his swaps.
Note: The number of inversions is the number of pair (i,j) where 1≤i<j≤n and ai>aj.
Input
The input consists of several tests. For each tests:
The first line contains 2 integers n,k (1≤n≤105,0≤k≤109). The second line contains n integers a1,a2,…,an (0≤ai≤109).
Output
For each tests:
A single integer denotes the minimum number of inversions.
Sample Input
3 1 2 2 1 3 0 2 2 1
Sample Output
1 2
Author
Xiaoxu Guo (ftiasch)
Source
2014 Multi-University Training Contest 5
Recommend
We have carefully selected several similar problems for you: 6460 6459 6458 6457 6456
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int a[100010];
int ans[100010];
ll solve (int l,int r){
ll num=0;
if(l==r) return 0;//出口
int mid=(l+r)>>1;
num+=solve(l,mid);
num+=solve(mid+1,r);
for(int i=l,j=mid+1,k=0;i<=mid||j<=r;k++){
if(i>mid) ans[k]=a[j++];
else if(j>r) ans[k]=a[i++];
else if(a[i]<=a[j]) ans[k]=a[i++];
else{
num+=mid-i+1;
ans[k]=a[j++];
}
}
for(int i=0;i<=(r-l);i++){
a[l+i]=ans[i];
}
return num;
}
int main(){
int n,k;
while(cin>>n>>k){
memset(a,0,sizeof(a));
memset(ans,0,sizeof(ans));
for(int i=1;i<=n;i++)
cin>>a[i];
ll res=solve(1,n);
if((res-k)>0) cout<<res-k<<endl;
else cout<<0<<endl;
}
return 0;
}
emmm,我错了很久,只是因为答案可能是long long。。。
要注意归并排序求逆序对的做法,除此之外,要注意每一次交换都可以减少一个逆序对,同时是最多减少一个。
幸运数字3.0
Description
444和777是两个幸运数字,我们定义,十进制表示中,每一位为444或者777的正整数都是幸运数字。
例如:444、777、444444、474747、747474、777777、444444444......
现在给你一个超级大的幸运数字,求出该数字中未出现的最小的幸运数字。
例如幸运数字447744774477,出现了444、777、474747,没有出现747474,所以447744774477中未出现的最小的幸运数字为747474
Input
第一行一个整数TTT,表示有TTT组数据(1≤T≤1000)(1 \le T \le 1000)(1≤T≤1000)
对于每组数据,输入第一行为正整数nnn,表示给定的幸运数字的长度
输入第二行为长度为nnn的幸运数字
输入保证,给定的幸运数字只含有数字444和数字777,长度小于5∗1055 * 10^55∗105
并且TTT组数据的总长度小于10610^6106
Output
对于每一组数据,先输出"Case x: m"(不含引号)
xxx表示第xxx组数据,从111开始编号,mmm表示未出现的最小的幸运数字的长度
第二行输出该幸运数字
Sample Input 1
2 3 447 11 44744477747
Sample Output 1
Case 1: 2 74 Case 2: 4 4444
Source
SGU142
#include <bits/stdc++.h>
using namespace std;
int f[20];
bool hhash[20][(1<<19)+1];
string s;
int main(){
ios::sync_with_stdio(false);
int t;
cin>>t;int ccase=0;
while(t--){
memset(hhash,0,sizeof(hhash));
int n;
cin>>n;
cin>>s;
f[0]=1;
for(int i=1;i<=19;i++){
f[i]=f[i-1]*2;
}
for(int i=1;i<=19&&i<=n;i++){
for(int j=0;j<=n-i&&f[i];j++){
int temp=0;
for(int l=j,k=0;k<i;k++,l++)temp=temp*2+(s[l]=='7');
if(!hhash[i][temp]) hhash[i][temp]=1,f[i]--;
}
}
for(int i=1;i<=19;i++){
if(f[i]==0) continue;
cout<<"Case "<<++ccase<<": "<<i<<endl;
for(int j=0;j<(1<<i);j++){
if(!hhash[i][j]){
for(int k=i-1;k>=0;k--){
if(j&(1<<k)) cout<<"7";else cout<<"4";
}
cout<<endl;
break;
}
}
break;
}
}
return 0;
}
根据数据范围判断可能最大长度,若是感觉没啥特殊的,那就。。。可能不需要什么特殊的东西,也就是说,一定长度所有情况数是一定的,又是两个数字,可以转化为0,1.判重,直接存进去,哈希吗。
种类数目
Description
有nnn个变量x1,x2...xnx_1,x_2...x_nx1,x2...xn,每个变量有一个取值范围[li,ri][l_i,r_i][li,ri],并且只取正整数
求S=∑i=1nxi2S=\sum_{i=1}^{n}x_i^2S=∑i=1nxi2的种类数目。
Input
输入只有一组数据,输入第一行为正整数nnn
接下来nnn行,每行两个正整数li,ril_i,r_ili,ri
(1≤n,li,ri≤100)(1 \le n, l_i, r_i \le 100)(1≤n,li,ri≤100)
Output
输出一行一个数字表示答案
Sample Input 1
5 1 2 2 3 3 4 4 5 5 6
Sample Output 1
26
Source
LOJ-515
#include<bits/stdc++.h>
using namespace std;
const int maxx=1e6+10;
int a[maxx];
int main(){
int n;
a[0]=1;//
cin>>n;int l,r;int least=0,most=0;
for(int i=1;i<=n;i++){
cin>>l>>r;
least+=l*l; most+=r*r;
for(int j=most;j>=least;j--){
a[j]=0;
for(int k=l;k<=r;k++){
if(j-k*k<least-l*l) break;
if(a[j-k*k]) {
a[j]=1;break;
}
}
}
}
int ans=0;
for(int i=least;i<=most;i++){
ans+=a[i];
}
cout<<ans<<endl;
return 0;
}
bool 不可以直接用来计数,但是bool比int快很多
一开始我在想这么多循环该怎么写
然后,应该想到子结构,一个个去凑,然后后面的在前面的基础上凑,为什么呢,因为在前面加和在后面加是一样的,因为可交换。