codeforces Hello 2018(A-E)
14893 ワード
A題
标题:m%2 nの値を求める
mの範囲は1 e 8しかないので、nが30未満の範囲を見るだけでいいです
B題
标题:1つのツリーで、非リーフノードが3つ以上のリーフノードに接続されていなければ、Noを出力し、そうでなければYesを出力する
bfsかdfsでやってもいいですよ.一度遍歴してみてください.ここで注意したいのはdfsの中でreturnを落とさないようにすることですね.ローカルマシンでは正しい結果が出ることもありますが、コンパイルするときにwaが出るかもしれません.あるいは、木を建てる過程の再帰(ポインタ)が1つも書かれていないことを思い出したり、プログラムに問題がなく、正しい結果が出たりして、私が何を考えているのか知っているかもしれません.
C題
标题:レモン水、容量によって、価格が违います.Lリットル以上のレモン水を买うには、少なくとも使うお金が必要です.第i容量に対応した価格が与えられ,容量は2 i−1であり,各容量は任意に購入できる.
最初の考えは欲張りだったが、waが来て、それからまるでリュックサックのように感じて、範囲を見て、だめだと感じて、それから欲張りだった...考えは単価順に、できるだけ単価が少ないものを持って、l容量を超えたら、現在の値を記録して、それから毎回超えて、値を記録して、最小は結果を記録したwa、、、最後にソート関数の問題であることに気づきました???
bool cmp(node a1,node a2)
{
if(abs(a1.per-a2.per).v>a2.v;
return a1.per.per;
}
単価が同じなら、体積によって大通りから小さく、そうでなければ単価によって小さいから大きいまで
単価が同じ考えを除けばAです...
もう一つのアイデアはバイナリに関係していて、巧みな感じがしますね~
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define ll long long
const double eps = 1e-6;
const ll inf = 1e18;
ll a[100];
int main()
{
int n,l;
scanf("%d %d",&n,&l);
for(int i=0;iscanf("%I64d",&a[i]);
for(int i=1;i1]*2ll);
for(int i=n-2;i>=0;i--)
a[i]=min(a[i],a[i+1]);
for(int i=n;i<=30;i++)
a[i]=a[i-1]*2ll;
ll ans = 0;
int i=0;
while(l)
{
if(l&1) ans = ans + a[i];
i++;
if(ans>a[i]) ans = a[i];
l=l/2;
}
if(a[i]printf("%I64d
",ans);
return 0;
}
D題
題意:n個の問題があり、時間制限はTであり、各問題のaiとtiを与え、tiは消費する時間を表す.T時間内にk個の問題が解決すると、m=解決の問題となる.ai>=k、の数量はmを求めて最大でいくらです.
何度もタイトルを読み始めても分からなかった....これは、優先順位キューであり、キューに格納される問題は解決され、ai>=q.size()である.
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define ll long long
const int maxn = 2*100000+10;
struct node {
int ai,ti,id;
operator < (const node&temp)const {
return ai>temp.ai;
}
}a[maxn];
priority_queueq;
bool cmp(node a1,node a2)
{
return a1.tiint main()
{
int n,t;
scanf("%d %d",&n,&t);
for(int i=1;i<=n;i++){
scanf("%d %d",&a[i].ai,&a[i].ti);
a[i].id = i;
}
sort(a+1,a+n+1,cmp);
int i;
for(i=1;i<=n;i++)
{
t-=a[i].ti;
if(t<0) break;
q.push(a[i]);
}
t+=a[i].ti;
while(!q.empty())
{
node a1 = q.top();
if(a1.aielse break;
}
for(;i<=n;i++)
{
int temp = t-a[i].ti;
if(temp<0) break;
if(a[i].ai1)) continue;// ,
q.push(a[i]);
t=temp;
node a1 = q.top();
if(a1.aiprintf("%d
",q.size());
printf("%d
",q.size());
if(q.size()>=1){
node a1 = q.top();
printf("%d",a1.id);q.pop();
while(!q.empty())
{
a1 = q.top();
printf(" %d",a1.id);
q.pop();
}
}
printf("
");
return 0;
}
E題
标题:x=0001111 b,y=00010011 b,z=0100101 bの3つの操作があり、優先度が高いから問題までそれぞれ!,&,|,もう一つ()は,n個の値を与え,x,y,zに対してどのような操作をすれば与えられた値になるかを尋ね,式を出力する.
これはdp F[i]:最後の操作は!T[i]:最後のステップ操作は&E[i]:最後のステップ操作は|状態遷移:F[i]はF[i^255]F[i]に移行可能T[i]T[i]に直接移行可能E[i]E[i]に移行可能F[i]に移行可能(((()で読めなくても大丈夫、直接コードを見て、コードがはっきり書いてある.
/*
by:sllsll
*/
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define inf 0x3f3f3f3f
#define ll long long
#define mem(a,b) memsert(a,b,sizeof(a))
#define rep(a,b) for(int i=(a);i
const int maxn = 1e5+10;
string F[maxn],T[maxn],E[maxn];
int x = 15,y=51,z=85;
int flag=0;
void fz(string&a,const string& b)
{
if(a=="")
{
flag=1;
a=b;return;
}
int size1 = a.length(),size2 = b.length();
//
if(size1>size2) a = b,flag=1;
else if(size1==size2)
if(a>b)a=b,flag=1;
}
void dp()
{
F[x]='x',F[y]='y',F[z]='z';
while(1)
{
flag=0;
rep(0,256)
if(F[i]!="")
fz(F[i^255],'!'+F[i]);
for(int i=0;i<256;i++)
if(F[i]!=""){
fz(T[i],F[i]);
for(int j=0;j<256;j++)
if(T[j]!="")
fz(T[i&j],F[i]+"&"+T[j]);
}
for(int i=0;i<256;i++)
if(T[i]!=""){
fz(E[i],T[i]);
for(int j=0;j<256;j++)
if(E[j]!="")
fz(E[i|j],T[i]+"|"+E[j]);
}
for(int i=0;i<256;i++)
if(E[i]!=""){
fz(F[i],"("+E[i]+")");
}
if(!flag) break;
}
}
int d[10]={128,64,32,16,8,4,2,1};
int change(string str)
{
int ans = 0;
for(int i=0;i<8;i++)
{
if(str[i]=='1') ans+=d[i];
}
return ans;
}
int main()
{
dp();
int T;
scanf("%d",&T);
while(T--)
{
string str;
cin>>str;
int n=change(str);
cout<return 0;
}
ps:一時変数を参照型パラメータとする場合はconstを付ける
もう一つの方法は最小生成ツリー転送であり,この差は多くなく,まずすべての値を計算し,ここのwhile(1)をwhile(!q.empty()に変更し,その後同じ転送である.